home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp95 / gnuchess.arc / gnuchess.c < prev    next >
C/C++ Source or Header  |  1992-01-16  |  79KB  |  3,443 lines

  1. /*
  2.   gnuchess.c - C source for GNU CHESS
  3.  
  4.   Revision: 1990-04-18
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  12.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  13.   the consequences of using it or for whether it serves any particular
  14.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  15.   General Public License for full details.
  16.  
  17.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  18.   only under the conditions described in the CHESS General Public License.
  19.   A copy of this license is supposed to have been given to you along with
  20.   CHESS so you can know your rights and responsibilities.  It should be in a
  21.   file named COPYING.  Among other things, the copyright notice and this
  22.   notice must be preserved on all copies.
  23. */
  24.  
  25.  
  26. #include "gnuchess.h"
  27.  
  28. #include <ctype.h>
  29.  
  30. #ifdef MSDOS
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <time.h>
  34. #define RWA_ACC "r+b"
  35. #define WA_ACC "w+b"
  36. #else
  37. #define RWA_ACC "r+"
  38. #define WA_ACC "w+"
  39. #include <sys/param.h>
  40. #include <sys/types.h>
  41. #include <sys/times.h>
  42. #endif /* MSDOS */
  43.  
  44. /* <stdlib.h> */
  45. extern int abs (int);
  46. extern int atoi (const char *);
  47. /* <time.h> */
  48. extern long int time (long int *);
  49. /* <string.h> */
  50. extern void *memset (void *, int, size_t);
  51.  
  52. #define valueP 100
  53. #define valueN 350
  54. #define valueB 355
  55. #define valueR 550
  56. #define valueQ 1100
  57. #define valueK 1200
  58. #define ctlP 0x4000
  59. #define ctlN 0x2800
  60. #define ctlB 0x1800
  61. #define ctlR 0x0400
  62. #define ctlQ 0x0200
  63. #define ctlK 0x0100
  64. #define ctlBQ 0x1200
  65. #define ctlBN 0x0800
  66. #define ctlRQ 0x0600
  67. #define ctlNN 0x2000
  68. #define Patak(c, u) (atak[c][u] > ctlP)
  69. #define Anyatak(c, u) (atak[c][u] > 0)
  70.  
  71. #if ttblsz
  72. #define truescore 0x0001
  73. #define lowerbound 0x0002
  74. #define upperbound 0x0004
  75. #define kingcastle 0x0008
  76. #define queencastle 0x0010
  77.  
  78. struct hashval
  79. {
  80.   unsigned long key,bd;
  81. };
  82. struct hashentry
  83. {
  84.   unsigned long hashbd;
  85.   unsigned short mv;
  86.   unsigned char flags, depth;    /* char saves some space */
  87.   short score;
  88. #ifdef HASHTEST
  89.   unsigned char bd[32];
  90. #endif /* HASHTEST */
  91.  
  92. };
  93.  
  94. #ifdef HASHFILE
  95. /*
  96.   persistent transposition table.
  97.   The size must be a power of 2. If you change the size,
  98.   be sure to run gnuchess -t before anything else.
  99. */
  100. #define frehash 6
  101. #ifdef MSDOS
  102. #define filesz (1 << 11)
  103. #else
  104. #define filesz (1 << 17)
  105. #endif /* MSDOS */
  106. struct fileentry
  107. {
  108.   unsigned char bd[32];
  109.   unsigned char f, t, flags, depth, sh, sl;
  110. };
  111. /*
  112.   In a networked enviroment gnuchess might be compiled on different
  113.   hosts with different random number generators, that is not acceptable
  114.   if they are going to share the same transposition table.
  115. */
  116. unsigned long int _near next = 1;
  117.  
  118. unsigned int urand (void)
  119. {
  120.   next *= 1103515245;
  121.   next += 12345;
  122.   return ((unsigned int) (next >> 16) & 0xFFFF);
  123. }
  124.  
  125. void srand (unsigned int seed)
  126. {
  127.   next = seed;
  128. }
  129. #else
  130. #define urand rand
  131. #endif /* HASHFILE */
  132.  
  133. static struct hashval hashcode[2][7][64];
  134. static struct hashentry huge ttable[2][ttblsz];
  135. #else /* ttblsz */
  136. # define    urand rand
  137. # endif
  138.  
  139. static unsigned long hashkey, hashbd;
  140. static short rpthash[2][256];
  141.  
  142. FILE *hashfile;
  143. struct leaf Tree[2000];
  144. struct leaf *_near root;
  145. short _near TrPnt[maxdepth];
  146. short _near PieceList[2][16], 
  147.     _near PawnCnt[2][8];
  148. #define wking PieceList[white][0]
  149. #define bking PieceList[black][0]
  150. #define EnemyKing PieceList[c2][0]
  151. long    _near NodeCnt, 
  152.     _near ETnodes, 
  153.     _near EvalNodes, 
  154.     _near HashCnt, 
  155.     _near FHashCnt, 
  156.     _near HashCol;
  157. long    _near ResponseTime, 
  158.     _near ExtraTime, 
  159.     _near Level, 
  160.     _near et, 
  161.     _near et0, 
  162.     _near time0, 
  163.     _near ft;
  164. short    _near Sdepth, 
  165.     _near GameCnt, 
  166.     _near Game50, 
  167.     _near MaxSearchDepth;
  168. short    _near TCflag, 
  169.     _near TCmoves, 
  170.     _near TCminutes, 
  171.     _near OperatorTime;
  172. short    _near opponent, 
  173.     _near computer, 
  174.     _near Awindow, 
  175.     _near Bwindow, 
  176.     _near dither, 
  177.     _near INCscore;
  178. short    _near player, 
  179.     _near xwndw, 
  180.     _near rehash;
  181. short    _near castld[2], 
  182.     _near Mvboard[64];
  183. short    _near epsquare, 
  184.     _near contempt;
  185. short svalue[64];
  186. struct BookEntry *_near Book;
  187. struct GameRec GameList[512];
  188. struct TimeControlRec _near TimeControl;
  189. struct flags _near flag;
  190. const short _near otherside[3] = {1, 0, 2};
  191. unsigned short _near hint, 
  192.         _near PrVar[maxdepth];
  193.  
  194. static short _near Pindex[64];
  195. static short _near PieceCnt[2];
  196. static short _near c1, 
  197.         _near c2, 
  198.         *_near atk1, 
  199.         *_near atk2, 
  200.         *_near PC1, 
  201.         *_near PC2, 
  202.         atak[2][64];
  203. static short _near mtl[2], 
  204.     _near pmtl[2], 
  205.     _near emtl[2], 
  206.     _near hung[2];
  207. static short _near FROMsquare, 
  208.     _near TOsquare, 
  209.     _near Zscore, 
  210.     _near zwndw;
  211. static short HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  212. static short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  213. static short Pscore[maxdepth], Tscore[maxdepth];
  214. static const short qrook[3] =
  215. {0, 56, 0};
  216. static const short krook[3] =
  217. {7, 63, 0};
  218. static const short kingP[3] =
  219. {4, 60, 0};
  220. static const short rank7[3] =
  221. {6, 1, 0};
  222. static const short sweep[8] =
  223. {false, false, false, true, true, true, false, false};
  224. static unsigned short killr0[maxdepth], killr1[maxdepth];
  225. static unsigned short killr2[maxdepth], killr3[maxdepth];
  226. static unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  227. static unsigned char history[8192];
  228.  
  229. static short Mwpawn[64], Mbpawn[64], Mknight[2][64], Mbishop[2][64];
  230. static short Mking[2][64], Kfield[2][64];
  231. static const short value[7] =
  232. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  233. static const short control[7] =
  234. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  235. static const short PassedPawn0[8] =
  236. {0, 60, 80, 120, 200, 360, 600, 800};
  237. static const short PassedPawn1[8] =
  238. {0, 30, 40, 60, 100, 180, 300, 800};
  239. static const short PassedPawn2[8] =
  240. {0, 15, 25, 35, 50, 90, 140, 800};
  241. static const short PassedPawn3[8] =
  242. {0, 5, 10, 15, 20, 30, 140, 800};
  243. static const short ISOLANI[8] =
  244. {-12, -16, -20, -24, -24, -20, -16, -12};
  245. static const short BACKWARD[16] =
  246. {-6, -10, -15, -21, -28, -28, -28, -28,
  247.  -28, -28, -28, -28, -28, -28, -28, -28};
  248. static const short BMBLTY[14] =
  249. {-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
  250. static const short RMBLTY[15] =
  251. {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
  252. static const short KTHRT[36] =
  253. {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
  254.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
  255.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
  256. static short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK;
  257. static short PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK;
  258. static short RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
  259. static short ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
  260. static short stage, stage2, Developed[2];
  261. static short PawnBonus, BishopBonus, RookBonus;
  262. static const short KingOpening[64] =
  263. {0, 0, -4, -10, -10, -4, 0, 0,
  264.  -4, -4, -8, -12, -12, -8, -4, -4,
  265.  -12, -16, -20, -20, -20, -20, -16, -12,
  266.  -16, -20, -24, -24, -24, -24, -20, -16,
  267.  -16, -20, -24, -24, -24, -24, -20, -16,
  268.  -12, -16, -20, -20, -20, -20, -16, -12,
  269.  -4, -4, -8, -12, -12, -8, -4, -4,
  270.  0, 0, -4, -10, -10, -4, 0, 0};
  271. static const short KingEnding[64] =
  272. {0, 6, 12, 18, 18, 12, 6, 0,
  273.  6, 12, 18, 24, 24, 18, 12, 6,
  274.  12, 18, 24, 30, 30, 24, 18, 12,
  275.  18, 24, 30, 36, 36, 30, 24, 18,
  276.  18, 24, 30, 36, 36, 30, 24, 18,
  277.  12, 18, 24, 30, 30, 24, 18, 12,
  278.  6, 12, 18, 24, 24, 18, 12, 6,
  279.  0, 6, 12, 18, 18, 12, 6, 0};
  280. static const short DyingKing[64] =
  281. {0, 8, 16, 24, 24, 16, 8, 0,
  282.  8, 32, 40, 48, 48, 40, 32, 8,
  283.  16, 40, 56, 64, 64, 56, 40, 16,
  284.  24, 48, 64, 72, 72, 64, 48, 24,
  285.  24, 48, 64, 72, 72, 64, 48, 24,
  286.  16, 40, 56, 64, 64, 56, 40, 16,
  287.  8, 32, 40, 48, 48, 40, 32, 8,
  288.  0, 8, 16, 24, 24, 16, 8, 0};
  289. static const short KBNK[64] =
  290. {99, 90, 80, 70, 60, 50, 40, 40,
  291.  90, 80, 60, 50, 40, 30, 20, 40,
  292.  80, 60, 40, 30, 20, 10, 30, 50,
  293.  70, 50, 30, 10, 0, 20, 40, 60,
  294.  60, 40, 20, 0, 10, 30, 50, 70,
  295.  50, 30, 10, 20, 30, 40, 60, 80,
  296.  40, 20, 30, 40, 50, 60, 80, 90,
  297.  40, 40, 50, 60, 70, 80, 90, 99};
  298. static const short pknight[64] =
  299. {0, 4, 8, 10, 10, 8, 4, 0,
  300.  4, 8, 16, 20, 20, 16, 8, 4,
  301.  8, 16, 24, 28, 28, 24, 16, 8,
  302.  10, 20, 28, 32, 32, 28, 20, 10,
  303.  10, 20, 28, 32, 32, 28, 20, 10,
  304.  8, 16, 24, 28, 28, 24, 16, 8,
  305.  4, 8, 16, 20, 20, 16, 8, 4,
  306.  0, 4, 8, 10, 10, 8, 4, 0};
  307. static const short pbishop[64] =
  308. {14, 14, 14, 14, 14, 14, 14, 14,
  309.  14, 22, 18, 18, 18, 18, 22, 14,
  310.  14, 18, 22, 22, 22, 22, 18, 14,
  311.  14, 18, 22, 22, 22, 22, 18, 14,
  312.  14, 18, 22, 22, 22, 22, 18, 14,
  313.  14, 18, 22, 22, 22, 22, 18, 14,
  314.  14, 22, 18, 18, 18, 18, 22, 14,
  315.  14, 14, 14, 14, 14, 14, 14, 14};
  316. static const short PawnAdvance[64] =
  317. {0, 0, 0, 0, 0, 0, 0, 0,
  318.  4, 4, 4, 0, 0, 4, 4, 4,
  319.  6, 8, 2, 10, 10, 2, 8, 6,
  320.  6, 8, 12, 16, 16, 12, 8, 6,
  321.  8, 12, 16, 24, 24, 16, 12, 8,
  322.  12, 16, 24, 32, 32, 24, 16, 12,
  323.  12, 16, 24, 32, 32, 24, 16, 12,
  324.  0, 0, 0, 0, 0, 0, 0, 0};
  325.  
  326.  
  327. /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  328.  
  329.  
  330. #define taxicab(a,b) taxidata[a][b]
  331. short distdata[64][64], taxidata[64][64];
  332.  
  333. static inline void
  334. Initialize_dist (void)
  335. {
  336.   register short a, b, d, di;
  337.  
  338.   for (a = 0; a < 64; a++)
  339.     for (b = 0; b < 64; b++)
  340.       {
  341.     d = abs (column (a) - column (b));
  342.     di = abs (row (a) - row (b));
  343.     taxidata[a][b] = d + di;
  344.     distdata[a][b] = (d > di ? d : di);
  345.       }
  346. }
  347.  
  348. const short Stboard[64] =
  349. {rook, knight, bishop, queen, king, bishop, knight, rook,
  350.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  351.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  352.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  353.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  354.  rook, knight, bishop, queen, king, bishop, knight, rook};
  355. const short Stcolor[64] =
  356. {white, white, white, white, white, white, white, white,
  357.  white, white, white, white, white, white, white, white,
  358.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  359.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  360.  black, black, black, black, black, black, black, black,
  361.  black, black, black, black, black, black, black, black};
  362. short _near board[64], 
  363.     _near color[64];
  364. static unsigned char nextpos[8][64][64];
  365. static unsigned char nextdir[8][64][64];
  366. /*
  367.   ptype is used to separate white and black pawns, like this;
  368.   ptyp = ptype[side][piece]
  369.   piece can be used directly in nextpos/nextdir when generating moves
  370.   for pieces that are not black pawns.
  371. */
  372. static const short ptype[2][8] =
  373. {
  374.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  375.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  376. static const short direc[8][8] =
  377. {
  378.   0, 0, 0, 0, 0, 0, 0, 0,
  379.   10, 9, 11, 0, 0, 0, 0, 0,
  380.   8, -8, 12, -12, 19, -19, 21, -21,
  381.   9, 11, -9, -11, 0, 0, 0, 0,
  382.   1, 10, -1, -10, 0, 0, 0, 0,
  383.   1, 10, -1, -10, 9, 11, -9, -11,
  384.   1, 10, -1, -10, 9, 11, -9, -11,
  385.   -10, -9, -11, 0, 0, 0, 0, 0};
  386. static const short max_steps[8] =
  387. {0, 2, 1, 7, 7, 7, 1, 2};
  388. static const short nunmap[120] =
  389. {
  390.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  391.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  392.   -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  393.   -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  394.   -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  395.   -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  396.   -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  397.   -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  398.   -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  399.   -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  400.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  401.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  402.  
  403.  
  404. void
  405. Initialize_moves (void)
  406.  
  407. /*
  408.   This procedure pre-calculates all moves for every piece from every square.
  409.   This data is stored in nextpos/nextdir and used later in the move generation
  410.   routines.
  411. */
  412.  
  413. {
  414.   short ptyp, po, p0, d, di, s, delta;
  415.   unsigned char *ppos, *pdir;
  416.   short dest[8][8];
  417.   short steps[8];
  418.   short sorted[8];
  419.  
  420.   for (ptyp = 0; ptyp < 8; ptyp++)
  421.     for (po = 0; po < 64; po++)
  422.       for (p0 = 0; p0 < 64; p0++)
  423.     {
  424.       nextpos[ptyp][po][p0] = (unsigned char) po;
  425.       nextdir[ptyp][po][p0] = (unsigned char) po;
  426.     }
  427.   for (ptyp = 1; ptyp < 8; ptyp++)
  428.     for (po = 21; po < 99; po++)
  429.       if (nunmap[po] >= 0)
  430.     {
  431.       ppos = nextpos[ptyp][nunmap[po]];
  432.       pdir = nextdir[ptyp][nunmap[po]];
  433.       /* dest is a function of direction and steps */
  434.       for (d = 0; d < 8; d++)
  435.         {
  436.           dest[d][0] = nunmap[po];
  437.           delta = direc[ptyp][d];
  438.           if (delta != 0)
  439.         {
  440.           p0 = po;
  441.           for (s = 0; s < max_steps[ptyp]; s++)
  442.             {
  443.               p0 = p0 + delta;
  444.               /*
  445.             break if (off board) or
  446.             (pawns only move two steps from home square)
  447.               */
  448.               if (nunmap[p0] < 0 || (ptyp == pawn || ptyp == bpawn)
  449.               && s > 0 && (d > 0 || Stboard[nunmap[po]] != pawn))
  450.             break;
  451.               else
  452.             dest[d][s] = nunmap[p0];
  453.             }
  454.         }
  455.           else
  456.         s = 0;
  457.  
  458.           /*
  459.             sort dest in number of steps order
  460.             currently no sort is done due to compability with
  461.             the move generation order in old gnu chess
  462.           */
  463.           steps[d] = s;
  464.           for (di = d; s > 0 && di > 0; di--)
  465.         if (steps[sorted[di - 1]] == 0)    /* should be: < s */
  466.           sorted[di] = sorted[di - 1];
  467.         else
  468.           break;
  469.           sorted[di] = d;
  470.         }
  471.  
  472.       /*
  473.         update nextpos/nextdir,
  474.         pawns have two threads (capture and no capture)
  475.       */
  476.       p0 = nunmap[po];
  477.       if (ptyp == pawn || ptyp == bpawn)
  478.         {
  479.           for (s = 0; s < steps[0]; s++)
  480.         {
  481.           ppos[p0] = (unsigned char) dest[0][s];
  482.           p0 = dest[0][s];
  483.         }
  484.           p0 = nunmap[po];
  485.           for (d = 1; d < 3; d++)
  486.         {
  487.           pdir[p0] = (unsigned char) dest[d][0];
  488.           p0 = dest[d][0];
  489.         }
  490.         }
  491.       else
  492.         {
  493.           pdir[p0] = (unsigned char) dest[sorted[0]][0];
  494.           for (d = 0; d < 8; d++)
  495.         for (s = 0; s < steps[sorted[d]]; s++)
  496.           {
  497.             ppos[p0] = (unsigned char) dest[sorted[d]][s];
  498.             p0 = dest[sorted[d]][s];
  499.             if (d < 7)
  500.               pdir[p0] = (unsigned char) dest[sorted[d + 1]][0];
  501.             /* else is already initialized */
  502.           }
  503.         }
  504.     }
  505. }
  506.  
  507. /* hmm.... shouldn`t main be moved to the interface routines */
  508. int
  509. main (int argc, char **argv)
  510. {
  511.   short int ahead = true, hash = true;
  512.   char *xwin = 0;
  513.  
  514.   while (argc > 1 && ((argv[1][0] == '-') || (argv[1][0] == '+')))
  515.     {
  516.       switch (argv[1][1])
  517.     {
  518.     case 'a':
  519.       ahead = (argv[1][0] == '-') ? false : true;
  520.       break;
  521.     case 'h':
  522.       hash = (argv[1][0] == '-') ? false : true;
  523.       break;
  524. #if ttblsz
  525. #ifdef HASHFILE
  526.     case 't': /* create or test persistent transposition table */ 
  527.       {
  528.         if ((hashfile = fopen (HASHFILE, RWA_ACC)) == NULL)
  529.           hashfile = fopen (HASHFILE , WA_ACC);
  530.         if (hashfile != NULL)
  531.           {
  532.         long i, j;
  533.         int nr[maxdepth];
  534.         struct fileentry n;
  535.         
  536.         printf("Counting transposition file entries, wait!\n");
  537.         for(i = 0; i < maxdepth; i++) nr[i] = 0;
  538.         fseek(hashfile, 0L, SEEK_END);
  539.         i = ftell(hashfile) / sizeof(struct fileentry);
  540.         fseek(hashfile, 0L, SEEK_SET);
  541.         for (j = 0; j < i; j++)
  542.           {
  543.             fread(&n, sizeof(struct fileentry), 1, hashfile);
  544.             if (n.depth)
  545.               {
  546.             nr[n.depth]++;
  547.             nr[0]++;
  548.               }
  549.           }
  550.         printf("The file contains %d entries out of max %d\n",
  551.                nr[0], i);
  552.         for(j = 1; j < maxdepth; j++) printf("%d ",nr[j]);
  553.         printf("\n");
  554.         if (i < filesz)
  555.           {
  556.             printf("Filling transposition file, wait!\n");
  557.             for(j = 0; j < 32; j++)
  558.               n.bd[j] = 0;
  559.             n.f = n.t = 0;
  560.             n.flags = 0;
  561.             n.depth = 0;
  562.             n.sh = n.sl = 0;
  563.             for (j = i; j < filesz; j++)
  564.               fwrite (&n, sizeof(struct fileentry), 1, hashfile);
  565.           }
  566.         fclose(hashfile);
  567.           }
  568.         return(0);
  569.         break;
  570.       }
  571. #endif /* HASHFILE */
  572. #endif /* ttblsz */
  573.     case 'x':
  574.       xwin = &argv[1][2];
  575.       break;
  576.     default:
  577.       fprintf (stderr, "Usage: gnuchess [-a] [-t] [-x xwndw]\n");
  578.     }
  579.       argv++;
  580.       argc--;
  581.     }
  582.   Level = 0;
  583.   TCflag = false;
  584.   OperatorTime = 0;
  585.   if (argc == 2)
  586.     Level = atoi (argv[1]);
  587.   if (argc == 3)
  588.     {
  589.       TCmoves = atoi (argv[1]);
  590.       TCminutes = atoi (argv[2]);
  591.       TCflag = true;
  592.     }
  593.   Initialize ();
  594.   Initialize_dist ();
  595.   Initialize_moves ();
  596.   NewGame ();
  597.   GetOpenings ();
  598.  
  599.   flag.easy = ahead;
  600.   flag.hash = hash;
  601.   if (xwin)
  602.     xwndw = atoi (xwin);
  603.  
  604.   hashfile = NULL;
  605. #if ttblsz
  606. #ifdef HASHFILE
  607.   hashfile = fopen (HASHFILE, RWA_ACC);
  608. #endif /* HASHFILE */
  609. #endif  /* ttblsz */
  610.   while (!(flag.quit))
  611.     {
  612.       if (flag.bothsides && !flag.mate)
  613.     SelectMove (opponent, 1);
  614.       else
  615.     InputCommand ();
  616.       if (!(flag.quit || flag.mate || flag.force))
  617.     SelectMove (computer, 1);
  618.     }
  619. #if ttblsz
  620. #ifdef HASHFILE
  621.   if (hashfile) fclose(hashfile);
  622. #endif /* HASHFILE */
  623. #endif /* ttblsz */
  624.  
  625.   ExitChess ();
  626.   return (0);
  627. }
  628.  
  629. void
  630. NewGame (void)
  631.  
  632. /*
  633.   Reset the board and other variables to start a new game.
  634. */
  635.  
  636. {
  637.   short l, c, p;
  638.  
  639.   stage = stage2 = -1;        /* the game is not yet started */
  640.   flag.mate = flag.quit = flag.reverse = flag.bothsides = false;
  641.   flag.force = false;
  642.   flag.hash = flag.post = flag.easy = flag.rcptr = true;
  643.   NodeCnt = et0 = epsquare = 0;
  644.   dither = 0;
  645.   Awindow = 90;
  646.   Bwindow = 90;
  647.   xwndw = 90;
  648.   MaxSearchDepth = 29;
  649.   contempt = 0;
  650.   GameCnt = 0;
  651.   Game50 = 1;
  652.   hint = 0x0C14;
  653.   ZeroRPT ();
  654.   Developed[white] = Developed[black] = false;
  655.   castld[white] = castld[black] = false;
  656.   PawnThreat[0] = CptrFlag[0] = false;
  657.   Pscore[0] = 12000;
  658.   Tscore[0] = 12000;
  659.   opponent = white;
  660.   computer = black;
  661.   for (l = 0; l < 2000; l++)
  662.     Tree[l].f = Tree[l].t = 0;
  663. #if ttblsz
  664.   rehash = 6;
  665.   ZeroTTable ();
  666.   srand ((unsigned int) 1);
  667.   for (c = white; c <= black; c++)
  668.     for (p = pawn; p <= king; p++)
  669.       for (l = 0; l < 64; l++)
  670.     {
  671.       hashcode[c][p][l].key = (((unsigned long) urand ()));
  672.       hashcode[c][p][l].key += (((unsigned long) urand ()) << 16);
  673.       hashcode[c][p][l].bd = (((unsigned long) urand ()));
  674.       hashcode[c][p][l].bd += (((unsigned long) urand ()) << 16);
  675.       if (sizeof(long) > 4)
  676.         {
  677.           hashcode[c][p][l].key += (((unsigned long) urand ()) << 32);
  678.           hashcode[c][p][l].key += (((unsigned long) urand ()) << 48);
  679.           hashcode[c][p][l].bd += (((unsigned long) urand ()) << 32);
  680.           hashcode[c][p][l].bd += (((unsigned long) urand ()) << 48);
  681.         }
  682.     }
  683. #endif /* ttblsz */
  684.   for (l = 0; l < 64; l++)
  685.     {
  686.       board[l] = Stboard[l];
  687.       color[l] = Stcolor[l];
  688.       Mvboard[l] = 0;
  689.     }
  690.   ClrScreen ();
  691.   if (TCflag)
  692.     SetTimeControl ();
  693.   else if (Level == 0)
  694.     SelectLevel ();
  695.   InitializeStats ();
  696.   time0 = time ((long *) 0);
  697.   ElapsedTime (1);
  698.   UpdateDisplay (0, 0, 1, 0);
  699. }
  700.  
  701.  
  702. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  703.  
  704. static inline void
  705. pick (short int p1, short int p2)
  706.  
  707. /*
  708.   Find the best move in the tree between indexes p1 and p2. Swap the best
  709.   move into the p1 element.
  710. */
  711.  
  712. {
  713.   register short p, s;
  714.   short p0, s0;
  715.   struct leaf temp;
  716.  
  717.   s0 = Tree[p1].score;
  718.   p0 = p1;
  719.   for (p = p1 + 1; p <= p2; p++)
  720.     if ((s = Tree[p].score) > s0)
  721.       {
  722.     s0 = s;
  723.     p0 = p;
  724.       }
  725.   if (p0 != p1)
  726.     {
  727.       temp = Tree[p1];
  728.       Tree[p1] = Tree[p0];
  729.       Tree[p0] = temp;
  730.     }
  731. }
  732.  
  733. void
  734. SelectMove (short int side, short int iop)
  735.  
  736.  
  737. /*
  738.   Select a move by calling function search() at progressively deeper ply
  739.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  740.   to +90 points is set around the score returned from the previous
  741.   iteration. If Sdepth != 0 then the program has correctly predicted the
  742.   opponents move and the search will start at a depth of Sdepth+1 rather
  743.   than a depth of 1.
  744. */
  745.  
  746. {
  747.   static short i, tempb, tempc, tempsf, tempst, xside, rpt;
  748.   static short alpha, beta, score;
  749.  
  750.   flag.timeout = false;
  751.   xside = otherside[side];
  752.   if (iop != 2)
  753.     player = side;
  754.   if (TCflag)
  755.     {
  756.       if ((TimeControl.moves[side] + 3) != 0)
  757.     ResponseTime = (TimeControl.clock[side]) /
  758.       (TimeControl.moves[side] + 3) -
  759.       OperatorTime;
  760.       else
  761.     ResponseTime = 0;
  762.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves + 1);
  763.     }
  764.   else
  765.     ResponseTime = Level;
  766.   if (iop == 2)
  767.     ResponseTime = 99999;
  768.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  769.     ResponseTime -= ft;
  770.   else if (ResponseTime < 1)
  771.     ResponseTime = 1;
  772.   ExtraTime = 0;
  773.   ExaminePosition ();
  774.   ScorePosition (side, &score);
  775.   /* Pscore[0] = -score; */
  776.   ShowSidetomove ();
  777.  
  778.   if (Sdepth == 0)
  779.     {
  780. #if ttblsz
  781.       /* ZeroTTable (); */
  782. #endif /* ttblsz */
  783.       SearchStartStuff (side);
  784. #ifdef NOMEMSET
  785.       for (i = 0; i < 8192; i++)
  786.     history[i] = 0;
  787. #else
  788.       memset ((char *) history, 0, sizeof (history));
  789. #endif /* NOMEMSET */
  790.       FROMsquare = TOsquare = -1;
  791.       PV = 0;
  792.       if (iop != 2)
  793.     hint = 0;
  794.       for (i = 0; i < maxdepth; i++)
  795.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  796.       alpha = score - 90;
  797.       beta = score + 90;
  798.       rpt = 0;
  799.       TrPnt[1] = 0;
  800.       root = &Tree[0];
  801.       MoveList (side, 1);
  802.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  803.     pick (i, TrPnt[2] - 1);
  804.       if (Book != NULL)
  805.     OpeningBook (&hint);
  806.       if (Book != NULL)
  807.     flag.timeout = true;
  808.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  809.       Zscore = 0;
  810.       zwndw = 20;
  811.     }
  812.   while (!flag.timeout && Sdepth < MaxSearchDepth)
  813.     {
  814.       Sdepth++;
  815.       ShowDepth (' ');
  816.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  817.       for (i = 1; i <= Sdepth; i++)
  818.     killr0[i] = PrVar[i];
  819.       if (score < alpha)
  820.     {
  821.       ShowDepth ('-');
  822.       ExtraTime = 10 * ResponseTime;
  823.       /* ZeroTTable (); */
  824.       score = search (side, 1, Sdepth, -9000, score, PrVar, &rpt);
  825.     }
  826.       if (score > beta && !(root->flags & exact))
  827.     {
  828.       ShowDepth ('+');
  829.       ExtraTime = 0;
  830.       /* ZeroTTable (); */
  831.       score = search (side, 1, Sdepth, score, 9000, PrVar, &rpt);
  832.     }
  833.       score = root->score;
  834.       if (!flag.timeout)
  835.     for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  836.       pick (i, TrPnt[2] - 1);
  837.       ShowResults (score, PrVar, '.');
  838.       for (i = 1; i <= Sdepth; i++)
  839.     killr0[i] = PrVar[i];
  840.       if (score > Zscore - zwndw && score > Tree[1].score + 250)
  841.     ExtraTime = 0;
  842.       else if (score > Zscore - 3 * zwndw)
  843.     ExtraTime = ResponseTime;
  844.       else
  845.     ExtraTime = 3 * ResponseTime;
  846.       if (root->flags & exact)
  847.     flag.timeout = true;
  848.       if (Tree[1].score < -9000)
  849.     flag.timeout = true;
  850.       if (4 * et > 2 * ResponseTime + ExtraTime)
  851.     flag.timeout = true;
  852.       if (!flag.timeout)
  853.     {
  854.       Tscore[0] = score;
  855.       if (Zscore == 0)
  856.         Zscore = score;
  857.       else
  858.         Zscore = (Zscore + score) / 2;
  859.     }
  860.       zwndw = 20 + abs (Zscore / 12);
  861.       beta = score + Bwindow;
  862.       if (Zscore < score)
  863.     alpha = Zscore - Awindow - zwndw;
  864.       else
  865.     alpha = score - Awindow - zwndw;
  866.     }
  867.  
  868.   score = root->score;
  869.   if (rpt >= 2 || score < -12000)
  870.     root->flags |= draw;
  871.   if (iop == 2)
  872.     return;
  873.   if (Book == NULL)
  874.     hint = PrVar[2];
  875.   ElapsedTime (1);
  876.  
  877.   if (score > -9999 && rpt <= 2)
  878.     {
  879.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  880.       algbr (root->f, root->t, (short) root->flags);
  881.     }
  882.   else
  883.     algbr (0, 0, 0);
  884.   OutputMove ();
  885.   if (score == -9999 || score == 9998)
  886.     flag.mate = true;
  887.   if (flag.mate)
  888.     hint = 0;
  889.   if ((board[root->t] == pawn)
  890.       || (root->flags & capture)
  891.       || (root->flags & cstlmask))
  892.     {
  893.       Game50 = GameCnt;
  894.       ZeroRPT ();
  895.     }
  896.   GameList[GameCnt].score = score;
  897.   GameList[GameCnt].nodes = NodeCnt;
  898.   GameList[GameCnt].time = (short) et;
  899.   GameList[GameCnt].depth = Sdepth;
  900.   if (TCflag)
  901.     {
  902.       TimeControl.clock[side] -= (et + OperatorTime);
  903.       if (--TimeControl.moves[side] == 0)
  904.     SetTimeControl ();
  905.     }
  906.   if ((root->flags & draw) && flag.bothsides)
  907.     flag.mate = true;
  908.   if (GameCnt > 470)
  909.     flag.mate = true; /* out of move store, you loose */
  910.   player = xside;
  911.   Sdepth = 0;
  912.   fflush (stdin);
  913. }
  914.  
  915. int
  916. cvt_move_to_number(char *s, short int side, int *skip)
  917. {    int    c1, r1, c2, r2;
  918.  
  919.     if (s[0] == 'o') {
  920.           if (s[4] == 'o') {
  921.             *skip = 5;
  922.             return side == black ? 0x3C3A : 0x0402;
  923.             }
  924.         *skip = 3;
  925.         return side == black ? 0x3C3E : 0x0406;
  926.         }
  927.     *skip = 4;
  928.     c1 = s[0] - 'a';
  929.     r1 = s[1] - '1';
  930.     c2 = s[2] - 'a';
  931.     r2 = s[3] - '1';
  932.     return (locn (r1, c1) << 8) | locn (r2, c2);
  933. }
  934. int
  935. parse (FILE *fd, short unsigned int *mv)
  936. {
  937.   int i;
  938.   char    *cp;
  939.   char s[100];
  940.  
  941.     if (fgets(s, sizeof s, fd) == NULL)
  942.         return -1;
  943.     if (s[0] == '\0' || s[0] == '!' || s[0] == ';')
  944.         return 0;
  945.  
  946.   mv[0] = cvt_move_to_number(s, white, &i);
  947.   cp = s + i;
  948.   while (*cp == ' ')
  949.       cp++;
  950.   if (*cp == '\n')
  951.       return 1;
  952.   mv[1] = cvt_move_to_number(cp, black, &i);
  953.   return 2;
  954. }
  955.  
  956. void
  957. GetOpenings (void)
  958.      
  959. /*
  960.    Read in the Opening Book file and parse the algebraic notation for a move
  961.    into an unsigned integer format indicating the from and to square. Create
  962.    a linked list of opening lines of play, with entry->next pointing to the
  963.    next line and entry->move pointing to a chunk of memory containing the
  964.    moves. More Opening lines of up to 256 half moves may be added to
  965.    gnuchess.book.
  966. */
  967. #ifndef BOOK
  968. #define BOOK "gnuchess.book"
  969. #endif /* BOOK */     
  970. {
  971.   FILE *fd;
  972.   int c, i, j;
  973.   /* char buffr[2048]; */
  974.   struct BookEntry *entry;
  975.   unsigned short mv[2], *mp, tmp[100];
  976.  
  977.   if ((fd = fopen (BOOK, "r")) == NULL)
  978.     fd = fopen ("gnuchess.book", "r");
  979.   if (fd == NULL) {
  980.     ShowMessage ("warning: can't find book.");
  981.     return;
  982.     }
  983.     /* setvbuf(fd,buffr,_IOFBF,2048); */
  984.     Book = NULL;
  985.     i = 0;
  986.     while ((c = parse (fd, mv)) >= 0) {
  987.         if (c == 2) {
  988.             tmp[++i] = mv[0];
  989.             tmp[++i] = mv[1];
  990.             continue;
  991.             }
  992.         if (c == 1) {
  993.             tmp[++i] = mv[0];
  994.             c = 0;
  995.             }
  996.         if (c == 0 && i > 0) {
  997.             entry = (struct BookEntry *) malloc (sizeof (struct BookEntry));
  998.             mp = (unsigned short *) malloc ((i + 1) * sizeof (unsigned short));
  999.             if (!entry || !mp) {
  1000.                 Book = NULL;
  1001.                 ShowMessage ("warning: can't load book, out of memory.");
  1002.                 return;
  1003.                 }
  1004.             entry->mv = mp;
  1005.             entry->next = Book;
  1006.             Book = entry;
  1007.             for (j = 1; j <= i; j++)
  1008.                 *(mp++) = tmp[j];
  1009.             *mp = 0;
  1010.             i = 0;
  1011.             }
  1012.         }
  1013.     fclose (fd);
  1014. }
  1015.  
  1016.  
  1017. void
  1018. OpeningBook (unsigned short *hint)
  1019.  
  1020. /*
  1021.   Go thru each of the opening lines of play and check for a match with the
  1022.   current game listing. If a match occurs, generate a random number. If this
  1023.   number is the largest generated so far then the next move in this line
  1024.   becomes the current "candidate". After all lines are checked, the
  1025.   candidate move is put at the top of the Tree[] array and will be played by
  1026.   the program. Note that the program does not handle book transpositions.
  1027. */
  1028.  
  1029. {
  1030.   register short j, pnt;
  1031.   unsigned short m, *mp;
  1032.   unsigned r, r0;
  1033.   struct BookEntry *p;
  1034.  
  1035.   srand ((unsigned int) time ((long *) 0));
  1036.   r0 = m = 0;
  1037.   p = Book;
  1038.   while (p != NULL)
  1039.     {
  1040.       mp = p->mv;
  1041.       for (j = 1; j <= GameCnt; j++)
  1042.     if (GameList[j].gmove != *(mp++))
  1043.       break;
  1044.       if (j > GameCnt)
  1045.     if ((r = urand ()) > r0)
  1046.       {
  1047.         r0 = r;
  1048.         m = *mp;
  1049.         *hint = *(++mp);
  1050.       }
  1051.       p = p->next;
  1052.     }
  1053.  
  1054.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  1055.     if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
  1056.       Tree[pnt].score = 0;
  1057.   pick (TrPnt[1], TrPnt[2] - 1);
  1058.   if (Tree[TrPnt[1]].score < 0)
  1059.     Book = NULL;
  1060. }
  1061.  
  1062.  
  1063. inline void
  1064. repetition (short int *cnt)
  1065.  
  1066. /*
  1067.   Check for draw by threefold repetition.
  1068. */
  1069.  
  1070. {
  1071.   register short i, c, f, t;
  1072.   short b[64];
  1073.   unsigned short m;
  1074.  
  1075.   *cnt = c = 0;
  1076.   if (GameCnt > Game50 + 3)
  1077.     {
  1078. #ifdef NOMEMSET
  1079.       for (i = 0; i < 64; b[i++] = 0) ;
  1080. #else
  1081.       memset ((char *) b, 0, sizeof (b));
  1082. #endif /* NOMEMSET */
  1083.       for (i = GameCnt; i > Game50; i--)
  1084.     {
  1085.       m = GameList[i].gmove;
  1086.       f = m >> 8;
  1087.       t = m & 0xFF;
  1088.       if (++b[f] == 0)
  1089.         c--;
  1090.       else
  1091.         c++;
  1092.       if (--b[t] == 0)
  1093.         c--;
  1094.       else
  1095.         c++;
  1096.       if (c == 0)
  1097.         (*cnt)++;
  1098.     }
  1099.     }
  1100. }
  1101.  
  1102. int
  1103. search (short int side,
  1104.     short int ply,
  1105.     short int depth,
  1106.     short int alpha,
  1107.     short int beta,
  1108.     short unsigned int *bstline,
  1109.     short int *rpt)
  1110.  
  1111. /*
  1112.   Perform an alpha-beta search to determine the score for the current board
  1113.   position. If depth <= 0 only capturing moves, pawn promotions and
  1114.   responses to check are generated and searched, otherwise all moves are
  1115.   processed. The search depth is modified for check evasions, certain
  1116.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  1117.   the nominal search depth.
  1118. */
  1119.  
  1120. #define UpdateSearchStatus \
  1121. {\
  1122.    if (flag.post) ShowCurrentMove(pnt,node->f,node->t);\
  1123.      if (pnt > TrPnt[1])\
  1124.        {\
  1125.       d = best-Zscore; e = best-node->score;\
  1126.         if (best < alpha) ExtraTime = 10*ResponseTime;\
  1127.         else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  1128.         else if (d > -zwndw) ExtraTime = 0;\
  1129.         else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  1130.         else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  1131.         else ExtraTime = 5*ResponseTime;\
  1132.         }\
  1133.         }
  1134. #define prune (cf && score+node->score < alpha)
  1135. #define ReCapture (flag.rcptr && score > alpha && score < beta &&\
  1136.            ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  1137. /* && depth == Sdepth-ply+1 */
  1138. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  1139. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  1140.             ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  1141.             ChkFlag[ply-2] != ChkFlag[ply-4])
  1142.  
  1143. {
  1144.   register short j, pnt;
  1145.   short best, tempb, tempc, tempsf, tempst;
  1146.   short xside, pbst, d, e, cf, score, rcnt, slk, InChk;
  1147.   unsigned short mv, nxtline[maxdepth];
  1148.   struct leaf *node, tmp;
  1149.  
  1150.   NodeCnt++;
  1151.   xside = otherside[side];
  1152.  
  1153.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  1154.     repetition (rpt);
  1155.   else
  1156.     *rpt = 0;
  1157.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  1158.   if (*rpt == 1 && ply > 1)
  1159.     return (0);
  1160.   /* if (*rpt >= 2) return(0); */
  1161.  
  1162.   score = evaluate (side, ply, alpha, beta, INCscore, &slk, &InChk);
  1163.   if (score > 9000)
  1164.     {
  1165.       bstline[ply] = 0;
  1166.       return (score);
  1167.     }
  1168.   if (depth > 0)
  1169.     {
  1170.       /* Allow opponent a chance to check again */
  1171.       if (InChk)
  1172.     depth = (depth < 2) ? 2 : depth;
  1173.       else if (PawnThreat[ply - 1] || ReCapture)
  1174.     ++depth;
  1175.     }
  1176.   else
  1177.     {
  1178.       if (score >= alpha &&
  1179.       (InChk || PawnThreat[ply - 1] || Parry))
  1180.     depth = 1;
  1181.       else if (score <= beta && MateThreat)
  1182.     depth = 1;
  1183.     }
  1184.  
  1185. #if ttblsz
  1186.   if (depth > 0 && flag.hash && ply > 1)
  1187.     {
  1188.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  1189. #ifdef HASHFILE    
  1190.     if (hashfile && (depth > 5) && (GameCnt < 12))
  1191.       ProbeFTable (side, depth, &alpha, &beta, &score);
  1192. #else
  1193.       /* do nothing */;
  1194. #endif /* HASHFILE */      
  1195.       bstline[ply] = PV;
  1196.       bstline[ply + 1] = 0;
  1197.       if (beta == -20000)
  1198.     return (score);
  1199.       if (alpha > beta)
  1200.     return (alpha);
  1201.     }
  1202. #endif /* ttblsz */
  1203.   if (Sdepth == 1)
  1204.     d = 7;
  1205.   else
  1206.     d = 11;
  1207.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  1208.     /* score >= beta ?? */
  1209.     return (score);
  1210.  
  1211.   if (ply > 1)
  1212.     if (depth > 0)
  1213.       MoveList (side, ply);
  1214.     else
  1215.       CaptureList (side, ply);
  1216.  
  1217.   if (TrPnt[ply] == TrPnt[ply + 1])
  1218.     return (score);
  1219.  
  1220.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  1221.  
  1222.   if (depth > 0)
  1223.     best = -12000;
  1224.   else
  1225.     best = score;
  1226.   if (best > alpha)
  1227.     alpha = best;
  1228.  
  1229.   for (pnt = pbst = TrPnt[ply];
  1230.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  1231.        pnt++)
  1232.     {
  1233.       if (ply > 1)
  1234.     pick (pnt, TrPnt[ply + 1] - 1);
  1235.       node = &Tree[pnt];
  1236.       mv = (node->f << 8) | node->t;
  1237.       nxtline[ply + 1] = 0;
  1238.  
  1239.       if (prune)
  1240.     break;
  1241.       if (ply == 1)
  1242.     UpdateSearchStatus;
  1243.  
  1244.       if (!(node->flags & exact))
  1245.     {
  1246.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1247.       CptrFlag[ply] = (node->flags & capture);
  1248.       PawnThreat[ply] = (node->flags & pwnthrt);
  1249.       Tscore[ply] = node->score;
  1250.       PV = node->reply;
  1251.       node->score = -search (xside, ply + 1,
  1252.                  (depth > 0) ? depth - 1 : 0,
  1253.                  -beta, -alpha,
  1254.                  nxtline, &rcnt);
  1255.       if (abs (node->score) > 9000)
  1256.         node->flags |= exact;
  1257.       else if (rcnt == 1)
  1258.         node->score /= 2;
  1259.       if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  1260.           (node->score == 9999 - ply && !ChkFlag[ply]))
  1261.         {
  1262.           node->flags |= draw;
  1263.           node->flags |= exact;
  1264.           if (side == computer)
  1265.         node->score = contempt;
  1266.           else
  1267.         node->score = -contempt;
  1268.         }
  1269.       node->reply = nxtline[ply + 1];
  1270.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1271.     }
  1272.       if (node->score > best && !flag.timeout)
  1273.     {
  1274.       if (depth > 0)
  1275.         if (node->score > alpha && !(node->flags & exact))
  1276.           node->score += depth;
  1277.       best = node->score;
  1278.       pbst = pnt;
  1279.       if (best > alpha)
  1280.         alpha = best;
  1281.       for (j = ply + 1; nxtline[j] > 0; j++)
  1282.         bstline[j] = nxtline[j];
  1283.       bstline[j] = 0;
  1284.       bstline[ply] = mv;
  1285.       if (ply == 1)
  1286.         {
  1287.           if (best > root->score)
  1288.         {
  1289.           tmp = Tree[pnt];
  1290.           for (j = pnt - 1; j >= 0; j--)
  1291.             Tree[j + 1] = Tree[j];
  1292.           Tree[0] = tmp;
  1293.           pbst = 0;
  1294.         }
  1295.           if (Sdepth > 2)
  1296.         if (best > beta)
  1297.           ShowResults (best, bstline, '+');
  1298.         else if (best < alpha)
  1299.           ShowResults (best, bstline, '-');
  1300.         else
  1301.           ShowResults (best, bstline, '&');
  1302.         }
  1303.     }
  1304.       if (NodeCnt > ETnodes)
  1305.     ElapsedTime (0);
  1306.       if (flag.timeout)
  1307.     return (-Tscore[ply - 1]);
  1308.     }
  1309.  
  1310.   node = &Tree[pbst];
  1311.   mv = (node->f << 8) | node->t;
  1312. #if ttblsz
  1313.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1314.     {
  1315.       PutInTTable (side, best, depth, alpha, beta, mv);
  1316. #ifdef HASHFILE      
  1317.       if (hashfile && (depth > 5) && (GameCnt < 12))
  1318.     PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  1319. #endif /* HASHFILE */      
  1320.     }
  1321. #endif /* ttblsz */
  1322.   if (depth > 0)
  1323.     {
  1324.       j = (node->f << 6) | node->t;
  1325.       if (side == black)
  1326.     j |= 0x1000;
  1327.       if (history[j] < 150)
  1328.     history[j] += (unsigned char) 2 * depth;
  1329.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1330.     if (best <= beta)
  1331.       killr3[ply] = mv;
  1332.     else if (mv != killr1[ply])
  1333.       {
  1334.         killr2[ply] = killr1[ply];
  1335.         killr1[ply] = mv;
  1336.       }
  1337.       if (best > 9000)
  1338.     killr0[ply] = mv;
  1339.       else
  1340.     killr0[ply] = 0;
  1341.     }
  1342.   return (best);
  1343. }
  1344.  
  1345. #if ttblsz
  1346. /*
  1347.   hashbd contains a 32 bit "signature" of the board position. hashkey
  1348.   contains a 16 bit code used to address the hash table. When a move is
  1349.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  1350.   the hashbd and hashkey values keeps things current.
  1351. */
  1352. #define UpdateHashbd(side, piece, f, t) \
  1353. {\
  1354.   if ((f) >= 0)\
  1355.     {\
  1356.       hashbd ^= hashcode[side][piece][f].bd;\
  1357.       hashkey ^= hashcode[side][piece][f].key;\
  1358.     }\
  1359.   if ((t) >= 0)\
  1360.     {\
  1361.       hashbd ^= hashcode[side][piece][t].bd;\
  1362.       hashkey ^= hashcode[side][piece][t].key;\
  1363.     }\
  1364. }
  1365.  
  1366. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  1367.            | (board[2 * (i)] << 4)\
  1368.            | (color[2 * (i) + 1] ? 0x8 : 0)\
  1369.            | (board[2 * (i) + 1]))
  1370.  
  1371. int
  1372. ProbeTTable (short int side,
  1373.          short int depth,
  1374.          short int *alpha,
  1375.          short int *beta,
  1376.          short int *score)
  1377.  
  1378. /*
  1379.   Look for the current board position in the transposition table.
  1380. */
  1381.  
  1382. {
  1383.   register struct hashentry *ptbl;
  1384.   register unsigned short i;
  1385.  
  1386.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  1387.  
  1388.   /* rehash max rehash times */
  1389.   for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  1390.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  1391.   if ((short) ptbl->depth >= depth && ptbl->hashbd == hashbd)
  1392.     {
  1393.       HashCnt++;
  1394. #ifdef HASHTEST
  1395.       for (i = 0; i < 32; i++)
  1396.     {
  1397.       if (ptbl->bd[i] != CB(i))
  1398.         {
  1399.           HashCol++;
  1400.           ShowMessage("ttable collision detected");
  1401.           break;
  1402.         }
  1403.     }
  1404. #endif /* HASHTEST */
  1405.  
  1406.       PV = ptbl->mv;
  1407.       if (ptbl->flags & truescore)
  1408.     {
  1409.       *score = ptbl->score;
  1410.       *beta = -20000;
  1411.     }
  1412. #if 0 /* commented out, why? */
  1413.       else if (ptbl->flags & upperbound)
  1414.     {
  1415.       if (ptbl->score < *beta) *beta = ptbl->score+1;
  1416.     }
  1417. #endif
  1418.       else if (ptbl->flags & lowerbound)
  1419.     {
  1420.       if (ptbl->score > *alpha)
  1421.         *alpha = ptbl->score - 1;
  1422.     }
  1423.       return(true);
  1424.     }
  1425.   return(false);
  1426. }
  1427.  
  1428. void
  1429. PutInTTable (short int side,
  1430.          short int score,
  1431.          short int depth,
  1432.          short int alpha,
  1433.          short int beta,
  1434.          short unsigned int mv)
  1435.  
  1436. /*
  1437.   Store the current board position in the transposition table.
  1438. */
  1439.  
  1440. {
  1441.   register struct hashentry *ptbl;
  1442.   register unsigned short i;
  1443.  
  1444.   ptbl = &ttable[side][hashkey & (ttblsz - 1)];
  1445.  
  1446.   /* rehash max rehash times */
  1447.   for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  1448.     ptbl = &ttable[side][(hashkey + i) & (ttblsz - 1)];
  1449.   if (depth >= ptbl->depth || ptbl->hashbd != hashbd)
  1450.     {
  1451.       ptbl->hashbd = hashbd;
  1452.       ptbl->depth = (unsigned char) depth;
  1453.       ptbl->score = score;
  1454.       ptbl->mv = mv;
  1455.       ptbl->flags = 0;
  1456.       if (score < alpha)
  1457.     ptbl->flags |= upperbound;
  1458.       else if (score > beta)
  1459.     ptbl->flags |= lowerbound;
  1460.       else
  1461.     ptbl->flags |= truescore;
  1462. #ifdef HASHTEST
  1463.       for (i = 0; i < 32; i++)
  1464.     {
  1465.       ptbl->bd[i] = CB(i);
  1466.     }
  1467. #endif /* HASHTEST */
  1468.     }
  1469. }
  1470.  
  1471. void
  1472. ZeroTTable (void)
  1473. {
  1474.   register int side, i;
  1475.  
  1476.   if (flag.hash)
  1477.     for (side = white; side <= black; side++)
  1478.       for (i = 0; i < ttblsz; i++)
  1479.     ttable[side][i].depth = 0;
  1480. }
  1481.  
  1482. #ifdef HASHFILE
  1483. int
  1484. ProbeFTable(short int side,
  1485.         short int depth,
  1486.         short int *alpha,
  1487.         short int *beta,
  1488.         short int *score)
  1489.  
  1490. /*
  1491.   Look for the current board position in the persistent transposition table.
  1492. */
  1493.  
  1494. {
  1495.   register unsigned short i, j;
  1496.   register unsigned long hashix;
  1497.   short s;
  1498.   struct fileentry new, t;
  1499.  
  1500.   if (side == white)
  1501.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1502.   else
  1503.     hashix = hashkey | 1 & (filesz - 1);
  1504.  
  1505.   for (i = 0; i < 32; i++)
  1506.     new.bd[i] = CB(i);
  1507.   new.flags = 0;
  1508.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1509.     new.flags |= queencastle;
  1510.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1511.     new.flags |= kingcastle;
  1512.  
  1513.   for (i = 0; i < frehash; i++)
  1514.     {
  1515.       fseek(hashfile,
  1516.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1517.         SEEK_SET);
  1518.       fread(&t, sizeof(struct fileentry), 1, hashfile);
  1519.       for (j = 0; j < 32; j++)
  1520.     if (t.bd[j] != new.bd[j])
  1521.       break;
  1522.       if (((short) t.depth >= depth) && (j >= 32)
  1523.       && (new.flags == (t.flags & (kingcastle | queencastle))))
  1524.     {
  1525.       FHashCnt++;
  1526.       PV = (t.f << 8) | t.t;
  1527.       s = (t.sh << 8) | t.sl;
  1528.       if (t.flags & truescore)
  1529.         {
  1530.           *score = s;
  1531.           *beta = -20000;
  1532.         }
  1533.       else if (t.flags & lowerbound)
  1534.         {
  1535.           if (s > *alpha)
  1536.         *alpha = s - 1;
  1537.         }
  1538.       return(true);
  1539.     }
  1540.     }
  1541.   return(false);
  1542. }
  1543.  
  1544. void
  1545. PutInFTable (short int side,
  1546.          short int score,
  1547.          short int depth,
  1548.          short int alpha,
  1549.          short int beta,
  1550.          short unsigned int f,
  1551.          short unsigned int t)
  1552.  
  1553. /*
  1554.   Store the current board position in the persistent transposition table.
  1555. */
  1556.  
  1557. {
  1558.   register unsigned short i;
  1559.   register unsigned long hashix;
  1560.   struct fileentry new, tmp;
  1561.  
  1562.   if (side == white)
  1563.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1564.   else
  1565.     hashix = hashkey | 1 & (filesz - 1);
  1566.  
  1567.   for (i = 0; i < 32; i++)
  1568.     new.bd[i] = CB(i);
  1569.   new.f = (unsigned char) f;
  1570.   new.t = (unsigned char) t;
  1571.   new.flags = 0;
  1572.   if (score < alpha)
  1573.     new.flags |= upperbound;
  1574.   else if (score > beta)
  1575.     new.flags |= lowerbound;
  1576.   else
  1577.     new.flags |= truescore;
  1578.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1579.     new.flags |= queencastle;
  1580.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1581.     new.flags |= kingcastle;
  1582.   new.depth = (unsigned char) depth;
  1583.   new.sh = (unsigned char) (score >> 8);
  1584.   new.sl = (unsigned char) (score & 0xFF);
  1585.  
  1586.   for (i = 0; i < frehash; i++)
  1587.     {
  1588.       fseek(hashfile,
  1589.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1590.         SEEK_SET);
  1591.       fread(&tmp, sizeof(struct fileentry), 1, hashfile);
  1592.       if ((short) tmp.depth <= depth)
  1593.     {
  1594.       fseek(hashfile,
  1595.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1)),
  1596.         SEEK_SET);
  1597.       fwrite (&new, sizeof(struct fileentry), 1, hashfile);
  1598.       break;
  1599.     }
  1600.     }
  1601. }
  1602. #endif /* HASHFILE */
  1603. #endif /* ttblsz */
  1604.  
  1605. void
  1606. ZeroRPT (void)
  1607. {
  1608.   register int side, i;
  1609.  
  1610.   for (side = white; side <= black; side++)
  1611.     for (i = 0; i < 256; i++)
  1612.       rpthash[side][i] = 0;
  1613. }
  1614.  
  1615. #define Link(from,to,flag,s) \
  1616. {\
  1617.    node->f = from; node->t = to;\
  1618.      node->reply = 0;\
  1619.        node->flags = flag;\
  1620.      node->score = s;\
  1621.        ++node;\
  1622.          ++TrPnt[ply+1];\
  1623.          }
  1624.  
  1625. static inline void
  1626. LinkMove (short int ply,
  1627.       short int f,
  1628.       short int t,
  1629.       short int flag,
  1630.       short int xside)
  1631.  
  1632. /*
  1633.   Add a move to the tree.  Assign a bonus to order the moves
  1634.   as follows:
  1635.   1. Principle variation
  1636.   2. Capture of last moved piece
  1637.   3. Other captures (major pieces first)
  1638.   4. Killer moves
  1639.   5. "history" killers
  1640. */
  1641.  
  1642. {
  1643.   register short s, z;
  1644.   register unsigned short mv;
  1645.   register struct leaf *node;
  1646.  
  1647.   node = &Tree[TrPnt[ply + 1]];
  1648.   mv = (f << 8) | t;
  1649.   s = 0;
  1650.   if (mv == Swag0)
  1651.     s = 2000;
  1652.   else if (mv == Swag1)
  1653.     s = 60;
  1654.   else if (mv == Swag2)
  1655.     s = 50;
  1656.   else if (mv == Swag3)
  1657.     s = 40;
  1658.   else if (mv == Swag4)
  1659.     s = 30;
  1660.   z = (f << 6) | t;
  1661.   if (xside == white)
  1662.     z |= 0x1000;
  1663.   s += history[z];
  1664.   if (color[t] != neutral)
  1665.     {
  1666.       if (t == TOsquare)
  1667.     s += 500;
  1668.       s += value[board[t]] - board[f];
  1669.     }
  1670.   if (board[f] == pawn)
  1671.     if (row (t) == 0 || row (t) == 7)
  1672.       {
  1673.     flag |= promote;
  1674.     s += 800;
  1675.     Link (f, t, flag | queen, s - 20000);
  1676.     s -= 200;
  1677.     Link (f, t, flag | knight, s - 20000);
  1678.     s -= 50;
  1679.     Link (f, t, flag | rook, s - 20000);
  1680.     flag |= bishop;
  1681.     s -= 50;
  1682.       }
  1683.     else if (row (t) == 1 || row (t) == 6)
  1684.       {
  1685.     flag |= pwnthrt;
  1686.     s += 600;
  1687.       }
  1688.   Link (f, t, flag, s - 20000);
  1689. }
  1690.  
  1691.  
  1692. static inline void
  1693. GenMoves (short int ply, short int sq, short int side, short int xside)
  1694.  
  1695. /*
  1696.   Generate moves for a piece. The moves are taken from the precalulated
  1697.   array nextpos/nextdir. If the board is free, next move is choosen from
  1698.   nextpos else from nextdir.
  1699. */
  1700.  
  1701. {
  1702.   register short u, piece;
  1703.   register unsigned char *ppos, *pdir;
  1704.  
  1705.   piece = board[sq];
  1706.   ppos = nextpos[ptype[side][piece]][sq];
  1707.   pdir = nextdir[ptype[side][piece]][sq];
  1708.   if (piece == pawn)
  1709.     {
  1710.       u = ppos[sq];    /* follow no captures thread */
  1711.       if (color[u] == neutral)
  1712.     {
  1713.       LinkMove (ply, sq, u, 0, xside);
  1714.       u = ppos[u];
  1715.       if (color[u] == neutral)
  1716.         LinkMove (ply, sq, u, 0, xside);
  1717.     }
  1718.       u = pdir[sq];    /* follow captures thread */
  1719.       if (color[u] == xside)
  1720.     LinkMove (ply, sq, u, capture, xside);
  1721.       else
  1722.     if (u == epsquare)
  1723.       LinkMove (ply, sq, u, capture | epmask, xside);
  1724.       u = pdir[u];
  1725.       if (color[u] == xside)
  1726.     LinkMove (ply, sq, u, capture, xside);
  1727.       else
  1728.     if (u == epsquare)
  1729.       LinkMove (ply, sq, u, capture | epmask, xside);
  1730.     }
  1731.   else
  1732.     {
  1733.       u = ppos[sq];
  1734.       do
  1735.     {
  1736.       if (color[u] == neutral)
  1737.         {
  1738.           LinkMove (ply, sq, u, 0, xside);
  1739.           u = ppos[u];
  1740.         }
  1741.       else
  1742.         {
  1743.           if (color[u] == xside)
  1744.         LinkMove (ply, sq, u, capture, xside);
  1745.           u = pdir[u];
  1746.         }
  1747.       } while (u != sq);
  1748.     }
  1749. }
  1750.  
  1751. void
  1752. MoveList (short int side, short int ply)
  1753.  
  1754. /*
  1755.   Fill the array Tree[] with all available moves for side to play. Array
  1756.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1757. */
  1758.  
  1759. {
  1760.   register short i, xside, f;
  1761.  
  1762.   xside = otherside[side];
  1763.   TrPnt[ply + 1] = TrPnt[ply];
  1764.   if (PV == 0)
  1765.     Swag0 = killr0[ply];
  1766.   else
  1767.     Swag0 = PV;
  1768.   Swag1 = killr1[ply];
  1769.   Swag2 = killr2[ply];
  1770.   Swag3 = killr3[ply];
  1771.   if (ply > 2)
  1772.     Swag4 = killr1[ply - 2];
  1773.   else
  1774.     Swag4 = 0;
  1775.   for (i = PieceCnt[side]; i >= 0; i--)
  1776.     GenMoves (ply, PieceList[side][i], side, xside);
  1777.   if (!castld[side])
  1778.     {
  1779.       f = PieceList[side][0];
  1780.       if (castle (side, f, f + 2, 0))
  1781.     {
  1782.       LinkMove (ply, f, f + 2, cstlmask, xside);
  1783.     }
  1784.       if (castle (side, f, f - 2, 0))
  1785.     {
  1786.       LinkMove (ply, f, f - 2, cstlmask, xside);
  1787.     }
  1788.     }
  1789. }
  1790.  
  1791. void
  1792. CaptureList (short int side, short int ply)
  1793.  
  1794. /*
  1795.   Fill the array Tree[] with all available cature and promote moves for
  1796.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1797.   of the first move at a ply.
  1798. */
  1799.  
  1800. {
  1801.   register short u, sq, xside;
  1802.   register struct leaf *node;
  1803.   register unsigned char *ppos, *pdir;
  1804.   short i, piece, *PL, r7;
  1805.  
  1806.   xside = otherside[side];
  1807.   TrPnt[ply + 1] = TrPnt[ply];
  1808.   node = &Tree[TrPnt[ply]];
  1809.   r7 = rank7[side];
  1810.   PL = PieceList[side];
  1811.   for (i = 0; i <= PieceCnt[side]; i++)
  1812.     {
  1813.       sq = PL[i];
  1814.       piece = board[sq];
  1815.       if (sweep[piece])
  1816.     {
  1817.       ppos = nextpos[piece][sq];
  1818.       pdir = nextdir[piece][sq];
  1819.       u = ppos[sq];
  1820.       do
  1821.         {
  1822.           if (color[u] == neutral)
  1823.         u = ppos[u];
  1824.           else
  1825.         {
  1826.           if (color[u] == xside)
  1827.             Link (sq, u, capture,
  1828.               value[board[u]] + svalue[board[u]] - piece);
  1829.           u = pdir[u];
  1830.         }
  1831.       } while (u != sq);
  1832.     }
  1833.       else
  1834.     {
  1835.       pdir = nextdir[ptype[side][piece]][sq];
  1836.       if (piece == pawn && row (sq) == r7)
  1837.         {
  1838.           u = pdir[sq];
  1839.           if (color[u] == xside)
  1840.         Link (sq, u, capture | promote | queen, valueQ);
  1841.           u = pdir[u];
  1842.           if (color[u] == xside)
  1843.         Link (sq, u, capture | promote | queen, valueQ);
  1844.           ppos = nextpos[ptype[side][piece]][sq];
  1845.           u = ppos[sq]; /* also generate non capture promote */
  1846.           if (color[u] == neutral)
  1847.         Link (sq, u, promote | queen, valueQ);
  1848.         }
  1849.       else
  1850.         {
  1851.           u = pdir[sq];
  1852.           do
  1853.         {
  1854.           if (color[u] == xside)
  1855.             Link (sq, u, capture,
  1856.               value[board[u]] + svalue[board[u]] - piece);
  1857.           u = pdir[u];
  1858.           } while (u != sq);
  1859.         }
  1860.     }
  1861.     }
  1862. }
  1863.  
  1864.  
  1865. int
  1866. castle (short int side, short int kf, short int kt, short int iop)
  1867.  
  1868. /* Make or Unmake a castling move. */
  1869.  
  1870. {
  1871.   register short rf, rt, t0, xside;
  1872.  
  1873.   xside = otherside[side];
  1874.   if (kt > kf)
  1875.     {
  1876.       rf = kf + 3;
  1877.       rt = kt - 1;
  1878.     }
  1879.   else
  1880.     {
  1881.       rf = kf - 4;
  1882.       rt = kt + 1;
  1883.     }
  1884.   if (iop == 0)
  1885.     {
  1886.       if (kf != kingP[side] ||
  1887.       board[kf] != king ||
  1888.       board[rf] != rook ||
  1889.       Mvboard[kf] != 0 ||
  1890.       Mvboard[rf] != 0 ||
  1891.       color[kt] != neutral ||
  1892.       color[rt] != neutral ||
  1893.       color[kt - 1] != neutral ||
  1894.       SqAtakd (kf, xside) ||
  1895.       SqAtakd (kt, xside) ||
  1896.       SqAtakd (rt, xside))
  1897.     return (false);
  1898.     }
  1899.   else
  1900.     {
  1901.       if (iop == 1)
  1902.     {
  1903.       castld[side] = true;
  1904.       Mvboard[kf]++;
  1905.       Mvboard[rf]++;
  1906.     }
  1907.       else
  1908.     {
  1909.       castld[side] = false;
  1910.       Mvboard[kf]--;
  1911.       Mvboard[rf]--;
  1912.       t0 = kt;
  1913.       kt = kf;
  1914.       kf = t0;
  1915.       t0 = rt;
  1916.       rt = rf;
  1917.       rf = t0;
  1918.     }
  1919.       board[kt] = king;
  1920.       color[kt] = side;
  1921.       Pindex[kt] = 0;
  1922.       board[kf] = no_piece;
  1923.       color[kf] = neutral;
  1924.       board[rt] = rook;
  1925.       color[rt] = side;
  1926.       Pindex[rt] = Pindex[rf];
  1927.       board[rf] = no_piece;
  1928.       color[rf] = neutral;
  1929.       PieceList[side][Pindex[kt]] = kt;
  1930.       PieceList[side][Pindex[rt]] = rt;
  1931. #if ttblsz
  1932.       UpdateHashbd (side, king, kf, kt);
  1933.       UpdateHashbd (side, rook, rf, rt);
  1934. #endif /* ttblsz */
  1935.     }
  1936.   return (true);
  1937. }
  1938.  
  1939.  
  1940. static inline void
  1941. EnPassant (short int xside, short int f, short int t, short int iop)
  1942.  
  1943. /*
  1944.   Make or unmake an en passant move.
  1945. */
  1946.  
  1947. {
  1948.   register short l;
  1949.  
  1950.   if (t > f)
  1951.     l = t - 8;
  1952.   else
  1953.     l = t + 8;
  1954.   if (iop == 1)
  1955.     {
  1956.       board[l] = no_piece;
  1957.       color[l] = neutral;
  1958.     }
  1959.   else
  1960.     {
  1961.       board[l] = pawn;
  1962.       color[l] = xside;
  1963.     }
  1964.   InitializeStats ();
  1965. }
  1966.  
  1967.  
  1968. static inline void
  1969. UpdatePieceList (short int side, short int sq, short int iop)
  1970.  
  1971. /*
  1972.   Update the PieceList and Pindex arrays when a piece is captured or when a
  1973.   capture is unmade.
  1974. */
  1975.  
  1976. {
  1977.   register short i;
  1978.   if (iop == 1)
  1979.     {
  1980.       PieceCnt[side]--;
  1981.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1982.     {
  1983.       PieceList[side][i] = PieceList[side][i + 1];
  1984.       Pindex[PieceList[side][i]] = i;
  1985.     }
  1986.     }
  1987.   else
  1988.     {
  1989.       PieceCnt[side]++;
  1990.       PieceList[side][PieceCnt[side]] = sq;
  1991.       Pindex[sq] = PieceCnt[side];
  1992.     }
  1993. }
  1994.  
  1995. void
  1996. MakeMove (short int side,
  1997.       struct leaf * node,
  1998.       short int *tempb,
  1999.       short int *tempc,
  2000.       short int *tempsf,
  2001.       short int *tempst,
  2002.       short int *INCscore)
  2003.  
  2004. /*
  2005.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  2006.   position obtained after making the move pointed to by node. Also update
  2007.   miscellaneous stuff that changes when a move is made.
  2008. */
  2009.  
  2010. {
  2011.   register short f, t, xside, ct, cf;
  2012.  
  2013.   xside = otherside[side];
  2014.   GameCnt++;
  2015.   f = node->f;
  2016.   t = node->t;
  2017.   epsquare = -1;
  2018.   FROMsquare = f;
  2019.   TOsquare = t;
  2020.   *INCscore = 0;
  2021.   GameList[GameCnt].gmove = (f << 8) | t;
  2022.   if (node->flags & cstlmask)
  2023.     {
  2024.       GameList[GameCnt].piece = no_piece;
  2025.       GameList[GameCnt].color = side;
  2026.       (void) castle (side, f, t, 1);
  2027.     }
  2028.   else
  2029.     {
  2030.       if (!(node->flags & capture) && (board[f] != pawn))
  2031.         rpthash[side][hashkey & 0xFF]++;
  2032.       *tempc = color[t];
  2033.       *tempb = board[t];
  2034.       *tempsf = svalue[f];
  2035.       *tempst = svalue[t];
  2036.       GameList[GameCnt].piece = *tempb;
  2037.       GameList[GameCnt].color = *tempc;
  2038.       if (*tempc != neutral)
  2039.     {
  2040.       UpdatePieceList (*tempc, t, 1);
  2041.       if (*tempb == pawn)
  2042.         --PawnCnt[*tempc][column (t)];
  2043.       if (board[f] == pawn)
  2044.         {
  2045.           --PawnCnt[side][column (f)];
  2046.           ++PawnCnt[side][column (t)];
  2047.           cf = column (f);
  2048.           ct = column (t);
  2049.           if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  2050.         *INCscore -= 15;
  2051.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  2052.         *INCscore += 15;
  2053.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  2054.         *INCscore -= 15;
  2055.         }
  2056.       mtl[xside] -= value[*tempb];
  2057.       if (*tempb == pawn)
  2058.         pmtl[xside] -= valueP;
  2059. #if ttblsz
  2060.       UpdateHashbd (xside, *tempb, -1, t);
  2061. #endif /* ttblsz */
  2062.       *INCscore += *tempst;
  2063.       Mvboard[t]++;
  2064.     }
  2065.       color[t] = color[f];
  2066.       board[t] = board[f];
  2067.       svalue[t] = svalue[f];
  2068.       Pindex[t] = Pindex[f];
  2069.       PieceList[side][Pindex[t]] = t;
  2070.       color[f] = neutral;
  2071.       board[f] = no_piece;
  2072.       if (board[t] == pawn)
  2073.     if (t - f == 16)
  2074.       epsquare = f + 8;
  2075.     else if (f - t == 16)
  2076.       epsquare = f - 8;
  2077.       if (node->flags & promote)
  2078.     {
  2079.       board[t] = node->flags & pmask;
  2080.       if (board[t] == queen)
  2081.         HasQueen[side]++;
  2082.       else if (board[t] == rook)
  2083.         HasRook[side]++;
  2084.       else if (board[t] == bishop)
  2085.         HasBishop[side]++;
  2086.       else if (board[t] == knight)
  2087.         HasKnight[side]++;
  2088.       --PawnCnt[side][column (t)];
  2089.       mtl[side] += value[board[t]] - valueP;
  2090.       pmtl[side] -= valueP;
  2091. #if ttblsz
  2092.       UpdateHashbd (side, pawn, f, -1);
  2093.       UpdateHashbd (side, board[t], f, -1);
  2094. #endif /* ttblsz */
  2095.       *INCscore -= *tempsf;
  2096.     }
  2097.       if (node->flags & epmask)
  2098.     EnPassant (xside, f, t, 1);
  2099.       else
  2100. #if ttblsz
  2101.     UpdateHashbd (side, board[t], f, t);
  2102. #else
  2103.     /* NOOP */;        
  2104. #endif /* ttblsz */
  2105.       Mvboard[f]++;
  2106.     }
  2107. }
  2108.  
  2109. void
  2110. UnmakeMove (short int side,
  2111.         struct leaf * node,
  2112.         short int *tempb,
  2113.         short int *tempc,
  2114.         short int *tempsf,
  2115.         short int *tempst)
  2116.  
  2117. /*
  2118.   Take back a move.
  2119. */
  2120.  
  2121. {
  2122.   register short f, t, xside, x;
  2123.  
  2124.   xside = otherside[side];
  2125.   f = node->f;
  2126.   t = node->t;
  2127.   epsquare = -1;
  2128.   GameCnt--;
  2129.   if (node->flags & cstlmask)
  2130.     (void) castle (side, f, t, 2);
  2131.   else
  2132.     {
  2133.       color[f] = color[t];
  2134.       board[f] = board[t];
  2135.       svalue[f] = *tempsf;
  2136.       Pindex[f] = Pindex[t];
  2137.       x = Pindex[f];
  2138.       PieceList[side][x] = f;
  2139.       color[t] = *tempc;
  2140.       board[t] = *tempb;
  2141.       svalue[t] = *tempst;
  2142.       if (node->flags & promote)
  2143.     {
  2144.       board[f] = pawn;
  2145.       ++PawnCnt[side][column (t)];
  2146.       mtl[side] += valueP - value[node->flags & pmask];
  2147.       pmtl[side] += valueP;
  2148. #if ttblsz
  2149.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  2150.       UpdateHashbd (side, pawn, -1, t);
  2151. #endif /* ttblsz */
  2152.     }
  2153.       if (*tempc != neutral)
  2154.     {
  2155.       UpdatePieceList (*tempc, t, 2);
  2156.       if (*tempb == pawn)
  2157.         ++PawnCnt[*tempc][column (t)];
  2158.       if (board[f] == pawn)
  2159.         {
  2160.           --PawnCnt[side][column (t)];
  2161.           ++PawnCnt[side][column (f)];
  2162.         }
  2163.       mtl[xside] += value[*tempb];
  2164.       if (*tempb == pawn)
  2165.         pmtl[xside] += valueP;
  2166. #if ttblsz
  2167.       UpdateHashbd (xside, *tempb, -1, t);
  2168. #endif /* ttblsz */
  2169.       Mvboard[t]--;
  2170.     }
  2171.       if (node->flags & epmask)
  2172.     EnPassant (xside, f, t, 2);
  2173.       else
  2174. #if ttblsz
  2175.     UpdateHashbd (side, board[f], f, t);
  2176. #else
  2177.       /* NOOP */;
  2178. #endif /* ttblsz */
  2179.       Mvboard[f]--;
  2180.       if (!(node->flags & capture) && (board[f] != pawn))
  2181.         rpthash[side][hashkey & 0xFF]--;
  2182.     }
  2183. }
  2184.  
  2185.  
  2186. void
  2187. InitializeStats (void)
  2188.  
  2189. /*
  2190.   Scan thru the board seeing what's on each square. If a piece is found,
  2191.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  2192.   determine the material for each side and set the hashkey and hashbd
  2193.   variables to represent the current board position. Array
  2194.   PieceList[side][indx] contains the location of all the pieces of either
  2195.   side. Array Pindex[sq] contains the indx into PieceList for a given
  2196.   square.
  2197. */
  2198.  
  2199. {
  2200.   register short i, sq;
  2201.   epsquare = -1;
  2202.   for (i = 0; i < 8; i++)
  2203.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  2204.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  2205.   PieceCnt[white] = PieceCnt[black] = 0;
  2206. #if ttblsz
  2207.   hashbd = hashkey = 0;
  2208. #endif /* ttblsz */
  2209.   for (sq = 0; sq < 64; sq++)
  2210.     if (color[sq] != neutral)
  2211.       {
  2212.     mtl[color[sq]] += value[board[sq]];
  2213.     if (board[sq] == pawn)
  2214.       {
  2215.         pmtl[color[sq]] += valueP;
  2216.         ++PawnCnt[color[sq]][column (sq)];
  2217.       }
  2218.     if (board[sq] == king)
  2219.       Pindex[sq] = 0;
  2220.     else
  2221.       Pindex[sq] = ++PieceCnt[color[sq]];
  2222.     PieceList[color[sq]][Pindex[sq]] = sq;
  2223. #if ttblsz
  2224.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  2225.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  2226. #endif /* ttblsz */
  2227.       }
  2228. }
  2229.  
  2230.  
  2231. int
  2232. SqAtakd (short int sq, short int side)
  2233.  
  2234. /*
  2235.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  2236.   Bishop, Rook and King and last Knight.
  2237. */
  2238.  
  2239. {
  2240.   register short u;
  2241.   register unsigned char *ppos, *pdir;
  2242.   short xside;
  2243.  
  2244.   xside = otherside[side];
  2245.   pdir = nextdir[ptype[xside][pawn]][sq];
  2246.   u = pdir[sq];        /* follow captures thread */
  2247.   if (u != sq)
  2248.     {
  2249.       if (board[u] == pawn && color[u] == side)
  2250.     return (true);
  2251.       u = pdir[u];
  2252.       if (u != sq && board[u] == pawn && color[u] == side)
  2253.     return (true);
  2254.     }
  2255.   /* king capture */
  2256.   if (distance (sq, PieceList[side][0]) == 1)
  2257.     return (true);
  2258.   /* try a queen bishop capture */
  2259.   ppos = nextpos[bishop][sq];
  2260.   pdir = nextdir[bishop][sq];
  2261.   u = ppos[sq];
  2262.   do
  2263.     {
  2264.       if (color[u] == neutral)
  2265.     u = ppos[u];
  2266.       else
  2267.     {
  2268.       if (color[u] == side &&
  2269.           (board[u] == queen || board[u] == bishop))
  2270.         return (true);
  2271.       u = pdir[u];
  2272.     }
  2273.   } while (u != sq);
  2274.   /* try a queen rook capture */
  2275.   ppos = nextpos[rook][sq];
  2276.   pdir = nextdir[rook][sq];
  2277.   u = ppos[sq];
  2278.   do
  2279.     {
  2280.       if (color[u] == neutral)
  2281.     u = ppos[u];
  2282.       else
  2283.     {
  2284.       if (color[u] == side &&
  2285.           (board[u] == queen || board[u] == rook))
  2286.         return (true);
  2287.       u = pdir[u];
  2288.     }
  2289.   } while (u != sq);
  2290.   /* try a knight capture */
  2291.   pdir = nextdir[knight][sq];
  2292.   u = pdir[sq];
  2293.   do
  2294.     {
  2295.       if (color[u] == side && board[u] == knight)
  2296.     return (true);
  2297.       u = pdir[u];
  2298.   } while (u != sq);
  2299.   return (false);
  2300. }
  2301.  
  2302. static inline void
  2303. ataks (short int side, short int *a)
  2304.  
  2305. /*
  2306.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  2307.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  2308.   total ataks to the square.
  2309. */
  2310.  
  2311. {
  2312.   register short u, c, sq;
  2313.   register unsigned char *ppos, *pdir;
  2314.   short i, piece, *PL;
  2315.  
  2316. #ifdef NOMEMSET
  2317.   for (u = 64; u; a[--u] = 0) ;
  2318. #else
  2319.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  2320. #endif /* NOMEMSET */
  2321.   PL = PieceList[side];
  2322.   for (i = PieceCnt[side]; i >= 0; i--)
  2323.     {
  2324.       sq = PL[i];
  2325.       piece = board[sq];
  2326.       c = control[piece];
  2327.       if (sweep[piece])
  2328.     {
  2329.       ppos = nextpos[piece][sq];
  2330.       pdir = nextdir[piece][sq];
  2331.       u = ppos[sq];
  2332.       do
  2333.         {
  2334.           a[u] = ++a[u] | c;
  2335.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2336.       } while (u != sq);
  2337.     }
  2338.       else
  2339.     {
  2340.       pdir = nextdir[ptype[side][piece]][sq];
  2341.       u = pdir[sq];    /* follow captures thread for pawns */
  2342.       do
  2343.         {
  2344.           a[u] = ++a[u] | c;
  2345.           u = pdir[u];
  2346.       } while (u != sq);
  2347.     }
  2348.     }
  2349. }
  2350.  
  2351.  
  2352. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  2353.  
  2354. int
  2355. evaluate (short int side,
  2356.       short int ply,
  2357.       short int alpha,
  2358.       short int beta,
  2359.       short int INCscore,
  2360.       short int *slk,
  2361.       short int *InChk)
  2362.  
  2363. /*
  2364.   Compute an estimate of the score by adding the positional score from the
  2365.   previous ply to the material difference. If this score falls inside a
  2366.   window which is 180 points wider than the alpha-beta window (or within a
  2367.   50 point window during quiescence search) call ScorePosition() to
  2368.   determine a score, otherwise return the estimated score. If one side has
  2369.   only a king and the other either has no pawns or no pieces then the
  2370.   function ScoreLoneKing() is called.
  2371. */
  2372.  
  2373. {
  2374.   register short evflag, xside;
  2375.   short s;
  2376.  
  2377.   xside = otherside[side];
  2378.   s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
  2379.   hung[white] = hung[black] = 0;
  2380.   *slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  2381.      (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
  2382.  
  2383.   if (*slk)
  2384.     evflag = false;
  2385.   else
  2386.     evflag =
  2387.       (ply == 1 || ply < Sdepth ||
  2388.        ((ply == Sdepth + 1 || ply == Sdepth + 2) &&
  2389.     (s > alpha - xwndw && s < beta + xwndw)) ||
  2390.        (ply > Sdepth + 2 && s >= alpha - 25 && s <= beta + 25));
  2391.  
  2392.   if (evflag)
  2393.     {
  2394.       EvalNodes++;
  2395.       ataks (side, atak[side]);
  2396.       if (Anyatak (side, PieceList[xside][0]))
  2397.     return (10001 - ply);
  2398.       ataks (xside, atak[xside]);
  2399.       *InChk = Anyatak (xside, PieceList[side][0]);
  2400.       ScorePosition (side, &s);
  2401.     }
  2402.   else
  2403.     {
  2404.       if (SqAtakd (PieceList[xside][0], side))
  2405.     return (10001 - ply);
  2406.       *InChk = SqAtakd (PieceList[side][0], xside);
  2407.       if (*slk)
  2408.     ScoreLoneKing (side, &s);
  2409.     }
  2410.  
  2411.   Pscore[ply] = s - mtl[side] + mtl[xside];
  2412.   if (*InChk)
  2413.     ChkFlag[ply - 1] = Pindex[TOsquare];
  2414.   else
  2415.     ChkFlag[ply - 1] = 0;
  2416.   return (s);
  2417. }
  2418.  
  2419.  
  2420. static inline int
  2421. ScoreKPK (short int side,
  2422.       short int winner,
  2423.       short int loser,
  2424.       short int king1,
  2425.       short int king2,
  2426.       short int sq)
  2427.  
  2428. /*
  2429.   Score King and Pawns versus King endings.
  2430. */
  2431.  
  2432. {
  2433.   register short s, r;
  2434.  
  2435.   if (PieceCnt[winner] == 1)
  2436.     s = 50;
  2437.   else
  2438.     s = 120;
  2439.   if (winner == white)
  2440.     {
  2441.       if (side == loser)
  2442.     r = row (sq) - 1;
  2443.       else
  2444.     r = row (sq);
  2445.       if (row (king2) >= r && distance (sq, king2) < 8 - r)
  2446.     s += 10 * row (sq);
  2447.       else
  2448.     s = 500 + 50 * row (sq);
  2449.       if (row (sq) < 6)
  2450.     sq += 16;
  2451.       else
  2452.     if (row(sq) == 6)
  2453.       sq += 8;
  2454.     }
  2455.   else
  2456.     {
  2457.       if (side == loser)
  2458.     r = row (sq) + 1;
  2459.       else
  2460.     r = row (sq);
  2461.       if (row (king2) <= r && distance (sq, king2) < r + 1)
  2462.     s += 10 * (7 - row (sq));
  2463.       else
  2464.     s = 500 + 50 * (7 - row (sq));
  2465.       if (row (sq) > 1)
  2466.     sq -= 16;
  2467.       else
  2468.     if (row(sq) == 1)
  2469.       sq -= 8;
  2470.     }
  2471.   s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
  2472.   return (s);
  2473. }
  2474.  
  2475.  
  2476. static inline int
  2477. ScoreKBNK (short int winner, short int king1, short int king2)
  2478.  
  2479.  
  2480. /*
  2481.   Score King+Bishop+Knight versus King endings.
  2482.   This doesn't work all that well but it's better than nothing.
  2483. */
  2484.  
  2485. {
  2486.   register short s, sq, KBNKsq = 0;
  2487.  
  2488.   for (sq = 0; sq < 64; sq++)
  2489.     if (board[sq] == bishop)
  2490.       if (row (sq) % 2 == column (sq) % 2)
  2491.     KBNKsq = 0;
  2492.       else
  2493.     KBNKsq = 7;
  2494.  
  2495.   s = emtl[winner] - 300;
  2496.   if (KBNKsq == 0)
  2497.     s += KBNK[king2];
  2498.   else
  2499.     s += KBNK[locn (row (king2), 7 - column (king2))];
  2500.   s -= taxicab (king1, king2);
  2501.   s -= distance (PieceList[winner][1], king2);
  2502.   s -= distance (PieceList[winner][2], king2);
  2503.   return (s);
  2504. }
  2505.  
  2506.  
  2507. void
  2508. ScoreLoneKing (short int side, short int *score)
  2509.  
  2510. /*
  2511.   Static evaluation when loser has only a king and winner has no pawns or no
  2512.   pieces.
  2513. */
  2514.  
  2515. {
  2516.   register short winner, loser, king1, king2, s, i;
  2517.  
  2518.   UpdateWeights ();
  2519.   if (mtl[white] > mtl[black])
  2520.     winner = white;
  2521.   else
  2522.     winner = black;
  2523.   loser = otherside[winner];
  2524.   king1 = PieceList[winner][0];
  2525.   king2 = PieceList[loser][0];
  2526.  
  2527.   s = 0;
  2528.  
  2529.   if (pmtl[winner] > 0)
  2530.     for (i = 1; i <= PieceCnt[winner]; i++)
  2531.       s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
  2532.  
  2533.   else if (emtl[winner] == valueB + valueN)
  2534.     s = ScoreKBNK (winner, king1, king2);
  2535.  
  2536.   else if (emtl[winner] > valueB)
  2537.     s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
  2538.  
  2539.   if (side == winner)
  2540.     *score = s;
  2541.   else
  2542.     *score = -s;
  2543. }
  2544.  
  2545.  
  2546. static inline void
  2547. BRscan (short int sq, short int *s, short int *mob)
  2548.  
  2549. /*
  2550.   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
  2551.   hung[] array if a pin is found.
  2552. */
  2553. {
  2554.   register short u, piece, pin;
  2555.   register unsigned char *ppos, *pdir;
  2556.   short *Kf;
  2557.  
  2558.   Kf = Kfield[c1];
  2559.   *mob = 0;
  2560.   piece = board[sq];
  2561.   ppos = nextpos[piece][sq];
  2562.   pdir = nextdir[piece][sq];
  2563.   u = ppos[sq];
  2564.   pin = -1;            /* start new direction */
  2565.   do
  2566.     {
  2567.       *s += Kf[u];
  2568.       if (color[u] == neutral)
  2569.     {
  2570.       (*mob)++;
  2571.       if (ppos[u] == pdir[u])
  2572.         pin = -1;        /* oops new direction */
  2573.       u = ppos[u];
  2574.     }
  2575.       else if (pin < 0)
  2576.     {
  2577.       if (board[u] == pawn || board[u] == king)
  2578.         u = pdir[u];
  2579.       else
  2580.         {
  2581.           if (ppos[u] != pdir[u])
  2582.         pin = u;    /* not on the edge and on to find a pin */
  2583.           u = ppos[u];
  2584.         }
  2585.     }
  2586.       else
  2587.     {
  2588.       if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
  2589.         {
  2590.           if (color[pin] == c2)
  2591.         {
  2592.           *s += PINVAL;
  2593.           if (atk2[pin] == 0 ||
  2594.               atk1[pin] > control[board[pin]] + 1)
  2595.             ++hung[c2];
  2596.         }
  2597.           else
  2598.         *s += XRAY;
  2599.         }
  2600.       pin = -1;        /* new direction */
  2601.       u = pdir[u];
  2602.     }
  2603.   } while (u != sq);
  2604. }
  2605.  
  2606.  
  2607. static inline void
  2608. KingScan (short int sq, short int *s)
  2609.  
  2610. /*
  2611.   Assign penalties if king can be threatened by checks, if squares
  2612.   near the king are controlled by the enemy (especially the queen),
  2613.   or if there are no pawns near the king.
  2614.   The following must be true:
  2615.   board[sq] == king
  2616.   c1 == color[sq]
  2617.   c2 == otherside[c1]
  2618. */
  2619.  
  2620. #define ScoreThreat \
  2621. if (color[u] != c2)\
  2622.   if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
  2623.   else *s -= 3
  2624.  
  2625. {
  2626.   register short u;
  2627.   register unsigned char *ppos, *pdir;
  2628.   register short cnt, ok;
  2629.  
  2630.   cnt = 0;
  2631.   if (HasBishop[c2] || HasQueen[c2])
  2632.     {
  2633.       ppos = nextpos[bishop][sq];
  2634.       pdir = nextdir[bishop][sq];
  2635.       u = ppos[sq];
  2636.       do
  2637.     {
  2638.       if (atk2[u] & ctlBQ)
  2639.         ScoreThreat;
  2640.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2641.       } while (u != sq);
  2642.     }
  2643.   if (HasRook[c2] || HasQueen[c2])
  2644.     {
  2645.       ppos = nextpos[rook][sq];
  2646.       pdir = nextdir[rook][sq];
  2647.       u = ppos[sq];
  2648.       do
  2649.     {
  2650.       if (atk2[u] & ctlRQ)
  2651.         ScoreThreat;
  2652.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2653.       } while (u != sq);
  2654.     }
  2655.   if (HasKnight[c2])
  2656.     {
  2657.       pdir = nextdir[knight][sq];
  2658.       u = pdir[sq];
  2659.       do
  2660.     {
  2661.       if (atk2[u] & ctlNN)
  2662.         ScoreThreat;
  2663.       u = pdir[u];
  2664.       } while (u != sq);
  2665.     }
  2666.   *s += (KSFTY * KTHRT[cnt]) / 16;
  2667.  
  2668.   cnt = 0;
  2669.   ok = false;
  2670.   pdir = nextpos[king][sq];
  2671.   u = pdir[sq];
  2672.   do
  2673.     {
  2674.       if (board[u] == pawn)
  2675.     ok = true;
  2676.       if (atk2[u] > atk1[u])
  2677.     {
  2678.       ++cnt;
  2679.       if (atk2[u] & ctlQ)
  2680.         if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
  2681.           *s -= 4 * KSFTY;
  2682.     }
  2683.       u = pdir[u];
  2684.   } while (u != sq);
  2685.   if (!ok)
  2686.     *s -= KSFTY;
  2687.   if (cnt > 1)
  2688.     *s -= KSFTY;
  2689. }
  2690.  
  2691.  
  2692. static inline int
  2693. trapped (short int sq)
  2694.  
  2695. /*
  2696.   See if the attacked piece has unattacked squares to move to.
  2697.   The following must be true:
  2698.   c1 == color[sq]
  2699.   c2 == otherside[c1]
  2700. */
  2701.  
  2702. {
  2703.   register short u, piece;
  2704.   register unsigned char *ppos, *pdir;
  2705.  
  2706.   piece = board[sq];
  2707.   ppos = nextpos[ptype[c1][piece]][sq];
  2708.   pdir = nextdir[ptype[c1][piece]][sq];
  2709.   if (piece == pawn)
  2710.     {
  2711.       u = ppos[sq];    /* follow no captures thread */
  2712.       if (color[u] == neutral)
  2713.     {
  2714.       if (atk1[u] >= atk2[u])
  2715.         return (false);
  2716.       if (atk2[u] < ctlP)
  2717.         {
  2718.           u = ppos[u];
  2719.           if (color[u] == neutral && atk1[u] >= atk2[u])
  2720.         return (false);
  2721.         }
  2722.     }
  2723.       u = pdir[sq];    /* follow captures thread */
  2724.       if (color[u] == c2)
  2725.     return (false);
  2726.       u = pdir[u];
  2727.       if (color[u] == c2)
  2728.     return (false);
  2729.     }
  2730.   else
  2731.     {
  2732.       u = ppos[sq];
  2733.       do
  2734.     {
  2735.       if (color[u] != c1)
  2736.         if (atk2[u] == 0 || board[u] >= piece)
  2737.           return (false);
  2738.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2739.       } while (u != sq);
  2740.     }
  2741.   return (true);
  2742. }
  2743.  
  2744.  
  2745. static inline int
  2746. PawnValue (short int sq, short int side)
  2747.  
  2748. /*
  2749.   Calculate the positional value for a pawn on 'sq'.
  2750. */
  2751.  
  2752. {
  2753.   register short j, fyle, rank;
  2754.   register short s, a1, a2, in_square, r, e;
  2755.  
  2756.   a1 = (atk1[sq] & 0x4FFF);
  2757.   a2 = (atk2[sq] & 0x4FFF);
  2758.   rank = row (sq);
  2759.   fyle = column (sq);
  2760.   s = 0;
  2761.   if (c1 == white)
  2762.     {
  2763.       s = Mwpawn[sq];
  2764.       if ((sq == 11 && color[19] != neutral)
  2765.           || (sq == 12 && color[20] != neutral))
  2766.     s += PEDRNK2B;
  2767.       if ((fyle == 0 || PC1[fyle - 1] == 0)
  2768.       && (fyle == 7 || PC1[fyle + 1] == 0))
  2769.     s += ISOLANI[fyle];
  2770.       else if (PC1[fyle] > 1)
  2771.     s += PDOUBLED;
  2772.       if (a1 < ctlP && atk1[sq + 8] < ctlP)
  2773.     {
  2774.       s += BACKWARD[a2 & 0xFF];
  2775.       if (PC2[fyle] == 0)
  2776.         s += PWEAKH;
  2777.       if (color[sq + 8] != neutral)
  2778.         s += PBLOK;
  2779.     }
  2780.       if (PC2[fyle] == 0)
  2781.     {
  2782.       if (side == black)
  2783.         r = rank - 1;
  2784.       else
  2785.         r = rank;
  2786.       in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
  2787.       if (a2 == 0 || side == white)
  2788.         e = 0;
  2789.       else
  2790.         e = 1;
  2791.       for (j = sq + 8; j < 64; j += 8)
  2792.         if (atk2[j] >= ctlP)
  2793.           {
  2794.         e = 2;
  2795.         break;
  2796.           }
  2797.         else if (atk2[j] > 0 || color[j] != neutral)
  2798.           e = 1;
  2799.       if (e == 2)
  2800.         s += (stage * PassedPawn3[rank]) / 10;
  2801.       else if (in_square || e == 1)
  2802.         s += (stage * PassedPawn2[rank]) / 10;
  2803.       else if (emtl[black] > 0)
  2804.         s += (stage * PassedPawn1[rank]) / 10;
  2805.       else
  2806.         s += PassedPawn0[rank];
  2807.     }
  2808.     }
  2809.   else if (c1 == black)
  2810.     {
  2811.       s = Mbpawn[sq];
  2812.       if ((sq == 51 && color[43] != neutral)
  2813.       || (sq == 52 && color[44] != neutral))
  2814.     s += PEDRNK2B;
  2815.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2816.       (fyle == 7 || PC1[fyle + 1] == 0))
  2817.     s += ISOLANI[fyle];
  2818.       else if (PC1[fyle] > 1)
  2819.     s += PDOUBLED;
  2820.       if (a1 < ctlP && atk1[sq - 8] < ctlP)
  2821.     {
  2822.       s += BACKWARD[a2 & 0xFF];
  2823.       if (PC2[fyle] == 0)
  2824.         s += PWEAKH;
  2825.       if (color[sq - 8] != neutral)
  2826.         s += PBLOK;
  2827.     }
  2828.       if (PC2[fyle] == 0)
  2829.     {
  2830.       if (side == white)
  2831.         r = rank + 1;
  2832.       else
  2833.         r = rank;
  2834.       in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
  2835.       if (a2 == 0 || side == black)
  2836.         e = 0;
  2837.       else
  2838.         e = 1;
  2839.       for (j = sq - 8; j >= 0; j -= 8)
  2840.         if (atk2[j] >= ctlP)
  2841.           {
  2842.         e = 2;
  2843.         break;
  2844.           }
  2845.         else if (atk2[j] > 0 || color[j] != neutral)
  2846.           e = 1;
  2847.       if (e == 2)
  2848.         s += (stage * PassedPawn3[7 - rank]) / 10;
  2849.       else if (in_square || e == 1)
  2850.         s += (stage * PassedPawn2[7 - rank]) / 10;
  2851.       else if (emtl[white] > 0)
  2852.         s += (stage * PassedPawn1[7 - rank]) / 10;
  2853.       else
  2854.         s += PassedPawn0[7 - rank];
  2855.     }
  2856.     }
  2857.   if (a2 > 0)
  2858.     {
  2859.       if (a1 == 0 || a2 > ctlP + 1)
  2860.     {
  2861.       s += HUNGP;
  2862.       ++hung[c1];
  2863.       if (trapped (sq))
  2864.         ++hung[c1];
  2865.     }
  2866.       else
  2867.     if (a2 > a1)
  2868.       s += ATAKD;
  2869.     }
  2870.   return (s);
  2871. }
  2872.  
  2873.  
  2874. static inline int
  2875. KnightValue (short int sq, short int side)
  2876.  
  2877. /*
  2878.   Calculate the positional value for a knight on 'sq'.
  2879. */
  2880.  
  2881. {
  2882.   register short s, a2, a1;
  2883.  
  2884.   s = Mknight[c1][sq];
  2885.   a2 = (atk2[sq] & 0x4FFF);
  2886.   if (a2 > 0)
  2887.     {
  2888.       a1 = (atk1[sq] & 0x4FFF);
  2889.       if (a1 == 0 || a2 > ctlBN + 1)
  2890.     {
  2891.       s += HUNGP;
  2892.       ++hung[c1];
  2893.       if (trapped (sq))
  2894.         ++hung[c1];
  2895.     }
  2896.       else
  2897.     if (a2 >= ctlBN || a1 < ctlP)
  2898.       s += ATAKD;
  2899.     }
  2900.   return (s);
  2901. }
  2902.  
  2903.  
  2904. static inline int
  2905. BishopValue (short int sq, short int side)
  2906.  
  2907. /*
  2908.   Calculate the positional value for a bishop on 'sq'.
  2909. */
  2910.  
  2911. {
  2912.   register short a2, a1;
  2913.   short s, mob;
  2914.  
  2915.   s = Mbishop[c1][sq];
  2916.   BRscan (sq, &s, &mob);
  2917.   s += BMBLTY[mob];
  2918.   a2 = (atk2[sq] & 0x4FFF);
  2919.   if (a2 > 0)
  2920.     {
  2921.       a1 = (atk1[sq] & 0x4FFF);
  2922.       if (a1 == 0 || a2 > ctlBN + 1)
  2923.     {
  2924.       s += HUNGP;
  2925.       ++hung[c1];
  2926.       if (trapped (sq))
  2927.         ++hung[c1];
  2928.     }
  2929.       else
  2930.     if (a2 >= ctlBN || a1 < ctlP)
  2931.       s += ATAKD;
  2932.     }
  2933.   return (s);
  2934. }
  2935.  
  2936.  
  2937. static inline int
  2938. RookValue (short int sq, short int side)
  2939.  
  2940. /*
  2941.   Calculate the positional value for a rook on 'sq'.
  2942. */
  2943.  
  2944. {
  2945.   register short fyle, a2, a1;
  2946.   short s, mob;
  2947.  
  2948.   s = RookBonus;
  2949.   BRscan (sq, &s, &mob);
  2950.   s += RMBLTY[mob];
  2951.   fyle = column (sq);
  2952.   if (PC1[fyle] == 0)
  2953.     s += RHOPN;
  2954.   if (PC2[fyle] == 0)
  2955.     s += RHOPNX;
  2956.   if (pmtl[c2] > 100 && row (sq) == rank7[c1])
  2957.     s += 10;
  2958.   if (stage > 2)
  2959.     s += 14 - taxicab (sq, EnemyKing);
  2960.   a2 = (atk2[sq] & 0x4FFF);
  2961.   if (a2 > 0)
  2962.     {
  2963.       a1 = (atk1[sq] & 0x4FFF);
  2964.       if (a1 == 0 || a2 > ctlR + 1)
  2965.     {
  2966.       s += HUNGP;
  2967.       ++hung[c1];
  2968.  
  2969.       if (trapped (sq))
  2970.         ++hung[c1];
  2971.     }
  2972.       else
  2973.     if (a2 >= ctlR || a1 < ctlP)
  2974.       s += ATAKD;
  2975.     }
  2976.   return (s);
  2977. }
  2978.  
  2979.  
  2980. static inline int
  2981. QueenValue (short int sq, short int side)
  2982.  
  2983. /*
  2984.   Calculate the positional value for a queen on 'sq'.
  2985. */
  2986.  
  2987. {
  2988.   register short s, a2, a1;
  2989.  
  2990.   s = (distance (sq, EnemyKing) < 3) ? 12 : 0;
  2991.   if (stage > 2)
  2992.     s += 14 - taxicab (sq, EnemyKing);
  2993.   a2 = (atk2[sq] & 0x4FFF);
  2994.   if (a2 > 0)
  2995.     {
  2996.       a1 = (atk1[sq] & 0x4FFF);
  2997.       if (a1 == 0 || a2 > ctlQ + 1)
  2998.     {
  2999.       s += HUNGP;
  3000.       ++hung[c1];
  3001.       if (trapped (sq))
  3002.         ++hung[c1];
  3003.     }
  3004.       else
  3005.     if (a2 >= ctlQ || a1 < ctlP)
  3006.       s += ATAKD;
  3007.     }
  3008.   return (s);
  3009. }
  3010.  
  3011.  
  3012. static inline int
  3013. KingValue (short int sq, short int side)
  3014.  
  3015. /*
  3016.   Calculate the positional value for a king on 'sq'.
  3017. */
  3018.  
  3019. {
  3020.   register short fyle, a2, a1;
  3021.   short s;
  3022.  
  3023.   s = Mking[c1][sq];
  3024.   if (KSFTY > 0)
  3025.     if (Developed[c2] || stage > 0)
  3026.       KingScan (sq, &s);
  3027.   if (castld[c1])
  3028.     s += KCASTLD;
  3029.   else if (Mvboard[kingP[c1]])
  3030.     s += KMOVD;
  3031.  
  3032.   fyle = column (sq);
  3033.   if (PC1[fyle] == 0)
  3034.     s += KHOPN;
  3035.   if (PC2[fyle] == 0)
  3036.     s += KHOPNX;
  3037.   switch (fyle)
  3038.     {
  3039.     case 5:
  3040.       if (PC1[7] == 0)
  3041.         s += KHOPN;
  3042.       if (PC2[7] == 0)
  3043.         s += KHOPNX;
  3044.       /* Fall through */
  3045.     case 4:
  3046.     case 6:
  3047.     case 0:
  3048.       if (PC1[fyle + 1] == 0)
  3049.         s += KHOPN;
  3050.       if (PC2[fyle + 1] == 0)
  3051.         s += KHOPNX;
  3052.       break;
  3053.     case 2:    
  3054.       if (PC1[0] == 0)
  3055.         s += KHOPN;
  3056.       if (PC2[0] == 0)
  3057.         s += KHOPNX;
  3058.       /* Fall through */
  3059.     case 3:
  3060.     case 1:
  3061.     case 7:  
  3062.       if (PC1[fyle - 1] == 0)
  3063.         s += KHOPN;
  3064.       if (PC2[fyle - 1] == 0)
  3065.         s += KHOPNX;
  3066.       break;
  3067.     default:
  3068.       /* Impossible! */
  3069.       break;
  3070.     }
  3071.  
  3072.   a2 = (atk2[sq] & 0x4FFF);
  3073.   if (a2 > 0)
  3074.     {
  3075.       a1 = (atk1[sq] & 0x4FFF);
  3076.       if (a1 == 0 || a2 > ctlK + 1)
  3077.     {
  3078.       s += HUNGP;
  3079.       ++hung[c1];
  3080.     }
  3081.       else
  3082.     s += ATAKD;
  3083.     }
  3084.   return (s);
  3085. }
  3086.  
  3087.  
  3088. void
  3089. ScorePosition (short int side, short int *score)
  3090.  
  3091. /*
  3092.   Perform normal static evaluation of board position. A score is generated
  3093.   for each piece and these are summed to get a score for each side.
  3094. */
  3095.  
  3096. {
  3097.   register short sq, s, i, xside;
  3098.   short pscore[2];
  3099.  
  3100.   UpdateWeights ();
  3101.   xside = otherside[side];
  3102.   pscore[white] = pscore[black] = 0;
  3103.  
  3104.   for (c1 = white; c1 <= black; c1++)
  3105.     {
  3106.       c2 = otherside[c1];
  3107.       atk1 = atak[c1];
  3108.       atk2 = atak[c2];
  3109.       PC1 = PawnCnt[c1];
  3110.       PC2 = PawnCnt[c2];
  3111.       for (i = PieceCnt[c1]; i >= 0; i--)
  3112.     {
  3113.       sq = PieceList[c1][i];
  3114.       switch (board[sq])
  3115.         {
  3116.         case pawn:
  3117.           s = PawnValue(sq, side);
  3118.           break;
  3119.         case knight:
  3120.           s = KnightValue(sq, side);
  3121.           break;
  3122.         case bishop:
  3123.           s = BishopValue(sq, side);
  3124.           break;
  3125.         case rook:
  3126.           s = RookValue(sq, side);
  3127.           break;
  3128.         case queen:
  3129.           s = QueenValue(sq, side);
  3130.           break;
  3131.         case king:
  3132.           s = KingValue(sq, side);
  3133.           break;
  3134.         default:
  3135.           s = 0;
  3136.           break;
  3137.         }
  3138.       pscore[c1] += s;
  3139.       svalue[sq] = s;
  3140.     }
  3141.     }
  3142.   if (hung[side] > 1)
  3143.     pscore[side] += HUNGX;
  3144.   if (hung[xside] > 1)
  3145.     pscore[xside] += HUNGX;
  3146.  
  3147.   *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
  3148.   if (dither)
  3149.     *score += urand () % dither;
  3150.  
  3151.   if (*score > 0 && pmtl[side] == 0)
  3152.     if (emtl[side] < valueR)
  3153.       *score = 0;
  3154.     else if (*score < valueR)
  3155.       *score /= 2;
  3156.   if (*score < 0 && pmtl[xside] == 0)
  3157.     if (emtl[xside] < valueR)
  3158.       *score = 0;
  3159.     else if (-*score < valueR)
  3160.       *score /= 2;
  3161.  
  3162.   if (mtl[xside] == valueK && emtl[side] > valueB)
  3163.     *score += 200;
  3164.   if (mtl[side] == valueK && emtl[xside] > valueB)
  3165.     *score -= 200;
  3166. }
  3167.  
  3168.  
  3169. static inline void
  3170. BlendBoard (const short int a[64], const short int b[64], short int c[64])
  3171. {
  3172.   register int sq;
  3173.  
  3174.   for (sq = 0; sq < 64; sq++)
  3175.     c[sq] = (a[sq] * (10 - stage) + b[sq] * stage) / 10;
  3176. }
  3177.  
  3178.  
  3179. static inline void
  3180. CopyBoard (const short int a[64], short int b[64])
  3181. {
  3182.   struct bd {
  3183.       short int xx[64];
  3184.     };
  3185.  
  3186.   *(struct bd *) b = *(struct bd *) a;
  3187. }
  3188.  
  3189. void
  3190. ExaminePosition (void)
  3191.  
  3192. /*
  3193.   This is done one time before the search is started. Set up arrays
  3194.   Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
  3195.   SqValue() function to determine the positional value of each piece.
  3196. */
  3197.  
  3198. {
  3199.   register short i, sq;
  3200.   short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, fyle, rank;
  3201.   static short PawnStorm = false;
  3202.  
  3203.   ataks (white, atak[white]);
  3204.   ataks (black, atak[black]);
  3205.   UpdateWeights ();
  3206.   HasKnight[white] = HasKnight[black] = 0;
  3207.   HasBishop[white] = HasBishop[black] = 0;
  3208.   HasRook[white] = HasRook[black] = 0;
  3209.   HasQueen[white] = HasQueen[black] = 0;
  3210.   for (side = white; side <= black; side++)
  3211.     for (i = PieceCnt[side]; i >= 0; i--)
  3212.       switch (board[PieceList[side][i]])
  3213.     {
  3214.     case knight:
  3215.       ++HasKnight[side];
  3216.       break;
  3217.     case bishop:
  3218.       ++HasBishop[side];
  3219.       break;
  3220.     case rook:
  3221.       ++HasRook[side];
  3222.       break;
  3223.     case queen:
  3224.       ++HasQueen[side];
  3225.       break;
  3226.     }
  3227.   if (!Developed[white])
  3228.     Developed[white] = (board[1] != knight && board[2] != bishop &&
  3229.             board[5] != bishop && board[6] != knight);
  3230.   if (!Developed[black])
  3231.     Developed[black] = (board[57] != knight && board[58] != bishop &&
  3232.             board[61] != bishop && board[62] != knight);
  3233.   if (!PawnStorm && stage < 5)
  3234.     PawnStorm = ((column (wking) < 3 && column (bking) > 4) ||
  3235.          (column (wking) > 4 && column (bking) < 3));
  3236.  
  3237.   CopyBoard (pknight, Mknight[white]);
  3238.   CopyBoard (pknight, Mknight[black]);
  3239.   CopyBoard (pbishop, Mbishop[white]);
  3240.   CopyBoard (pbishop, Mbishop[black]);
  3241.   BlendBoard (KingOpening, KingEnding, Mking[white]);
  3242.   BlendBoard (KingOpening, KingEnding, Mking[black]);
  3243.  
  3244.   for (sq = 0; sq < 64; sq++)
  3245.     {
  3246.       fyle = column (sq);
  3247.       rank = row (sq);
  3248.       wstrong = bstrong = true;
  3249.       for (i = sq; i < 64; i += 8)
  3250.     if (Patak (black, i))
  3251.       {
  3252.         wstrong = false;
  3253.         break;
  3254.       }
  3255.       for (i = sq; i >= 0; i -= 8)
  3256.     if (Patak (white, i))
  3257.       {
  3258.         bstrong = false;
  3259.         break;
  3260.       }
  3261.       wpadv = bpadv = PADVNCM;
  3262.       if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) &&
  3263.       (fyle == 7 || PawnCnt[white][fyle + 1] == 0))
  3264.     wpadv = PADVNCI;
  3265.       if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) &&
  3266.       (fyle == 7 || PawnCnt[black][fyle + 1] == 0))
  3267.     bpadv = PADVNCI;
  3268.       Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
  3269.       Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
  3270.       Mwpawn[sq] += PawnBonus;
  3271.       Mbpawn[sq] += PawnBonus;
  3272.       if (Mvboard[kingP[white]])
  3273.     {
  3274.       if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
  3275.         Mwpawn[sq] += PAWNSHIELD;
  3276.     }
  3277.       else if (rank < 3 && (fyle < 2 || fyle > 5))
  3278.     Mwpawn[sq] += PAWNSHIELD / 2;
  3279.       if (Mvboard[kingP[black]])
  3280.     {
  3281.       if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
  3282.         Mbpawn[sq] += PAWNSHIELD;
  3283.     }
  3284.       else if (rank > 4 && (fyle < 2 || fyle > 5))
  3285.     Mbpawn[sq] += PAWNSHIELD / 2;
  3286.       if (PawnStorm)
  3287.     {
  3288.       if ((column (wking) < 4 && fyle > 4) ||
  3289.           (column (wking) > 3 && fyle < 3))
  3290.         Mwpawn[sq] += 3 * rank - 21;
  3291.       if ((column (bking) < 4 && fyle > 4) ||
  3292.           (column (bking) > 3 && fyle < 3))
  3293.         Mbpawn[sq] -= 3 * rank;
  3294.     }
  3295.       Mknight[white][sq] += 5 - distance (sq, bking);
  3296.       Mknight[white][sq] += 5 - distance (sq, wking);
  3297.       Mknight[black][sq] += 5 - distance (sq, wking);
  3298.       Mknight[black][sq] += 5 - distance (sq, bking);
  3299.       Mbishop[white][sq] += BishopBonus;
  3300.       Mbishop[black][sq] += BishopBonus;
  3301.       for (i = PieceCnt[black]; i >= 0; i--)
  3302.     if (distance (sq, PieceList[black][i]) < 3)
  3303.       Mknight[white][sq] += KNIGHTPOST;
  3304.       for (i = PieceCnt[white]; i >= 0; i--)
  3305.     if (distance (sq, PieceList[white][i]) < 3)
  3306.       Mknight[black][sq] += KNIGHTPOST;
  3307.       if (wstrong)
  3308.     Mknight[white][sq] += KNIGHTSTRONG;
  3309.       if (bstrong)
  3310.     Mknight[black][sq] += KNIGHTSTRONG;
  3311.       if (wstrong)
  3312.     Mbishop[white][sq] += BISHOPSTRONG;
  3313.       if (bstrong)
  3314.     Mbishop[black][sq] += BISHOPSTRONG;
  3315.  
  3316.       if (HasBishop[white] == 2)
  3317.     Mbishop[white][sq] += 8;
  3318.       if (HasBishop[black] == 2)
  3319.     Mbishop[black][sq] += 8;
  3320.       if (HasKnight[white] == 2)
  3321.     Mknight[white][sq] += 5;
  3322.       if (HasKnight[black] == 2)
  3323.     Mknight[black][sq] += 5;
  3324.  
  3325.       Kfield[white][sq] = Kfield[black][sq] = 0;
  3326.       if (distance (sq, wking) == 1)
  3327.     Kfield[black][sq] = KATAK;
  3328.       if (distance (sq, bking) == 1)
  3329.     Kfield[white][sq] = KATAK;
  3330.  
  3331.       Pd = 0;
  3332.       for (k = 0; k <= PieceCnt[white]; k++)
  3333.     {
  3334.       i = PieceList[white][k];
  3335.       if (board[i] == pawn)
  3336.         {
  3337.           pp = true;
  3338.           if (row (i) == 6)
  3339.         z = i + 8;
  3340.           else
  3341.         z = i + 16;
  3342.           for (j = i + 8; j < 64; j += 8)
  3343.         if (Patak (black, j) || board[j] == pawn)
  3344.           {
  3345.             pp = false;
  3346.             break;
  3347.           }
  3348.           if (pp)
  3349.         Pd += 5 * taxicab (sq, z);
  3350.           else
  3351.         Pd += taxicab (sq, z);
  3352.         }
  3353.     }
  3354.       for (k = 0; k <= PieceCnt[black]; k++)
  3355.     {
  3356.       i = PieceList[black][k];
  3357.       if (board[i] == pawn)
  3358.         {
  3359.           pp = true;
  3360.           if (row (i) == 1)
  3361.         z = i - 8;
  3362.           else
  3363.         z = i - 16;
  3364.           for (j = i - 8; j >= 0; j -= 8)
  3365.         if (Patak (white, j) || board[j] == pawn)
  3366.           {
  3367.             pp = false;
  3368.             break;
  3369.           }
  3370.           if (pp)
  3371.         Pd += 5 * taxicab (sq, z);
  3372.           else
  3373.         Pd += taxicab (sq, z);
  3374.         }
  3375.     }
  3376.       if (Pd != 0)
  3377.     {
  3378.       val = (Pd * stage2) / 10;
  3379.       Mking[white][sq] -= val;
  3380.       Mking[black][sq] -= val;
  3381.     }
  3382.     }
  3383. }
  3384.  
  3385. void
  3386. UpdateWeights (void)
  3387.  
  3388. /*
  3389.   If material balance has changed, determine the values for the positional
  3390.   evaluation terms.
  3391. */
  3392.  
  3393. {
  3394.   register short tmtl, s1;
  3395.  
  3396.   emtl[white] = mtl[white] - pmtl[white] - valueK;
  3397.   emtl[black] = mtl[black] - pmtl[black] - valueK;
  3398.   tmtl = emtl[white] + emtl[black];
  3399.   s1 = (tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520);
  3400.   if (s1 != stage)
  3401.     {
  3402.       stage = s1;
  3403.       stage2 = (tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220);
  3404.       PEDRNK2B = -15;    /* centre pawn on 2nd rank & blocked */
  3405.       PBLOK = -4;        /* blocked backward pawn */
  3406.       PDOUBLED = -14;    /* doubled pawn */
  3407.       PWEAKH = -4;        /* weak pawn on half open file */
  3408.       PAWNSHIELD = 10 - stage;    /* pawn near friendly king */
  3409.       PADVNCM = 10;        /* advanced pawn multiplier */
  3410.       PADVNCI = 7;        /* muliplier for isolated pawn */
  3411.       PawnBonus = stage;
  3412.       
  3413.       KNIGHTPOST = (stage + 2) / 3;    /* knight near enemy pieces */
  3414.       KNIGHTSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3415.       
  3416.       BISHOPSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3417.       BishopBonus = 2 * stage;
  3418.       
  3419.       RHOPN = 10;        /* rook on half open file */
  3420.       RHOPNX = 4;
  3421.       RookBonus = 6 * stage;
  3422.       
  3423.       XRAY = 8;        /* Xray attack on piece */
  3424.       PINVAL = 10;        /* Pin */
  3425.       
  3426.       KHOPN = (3 * stage - 30) / 2;    /* king on half open file */
  3427.       KHOPNX = KHOPN / 2;
  3428.       KCASTLD = 10 - stage;
  3429.       KMOVD = -40 / (stage + 1);    /* king moved before castling */
  3430.       KATAK = (10 - stage) / 2;    /* B,R attacks near enemy king */
  3431.       if (stage < 8)
  3432.     KSFTY = 16 - 2 * stage;
  3433.       else
  3434.     KSFTY = 0;
  3435.       
  3436.       ATAKD = -6;        /* defender > attacker */
  3437.       HUNGP = -8;        /* each hung piece */
  3438.       HUNGX = -12;        /* extra for >1 hung piece */
  3439.     }
  3440. }
  3441.  
  3442.  
  3443.